xref: /titanic_51/usr/src/uts/common/inet/kssl/ksslrec.c (revision 9b1bd49f83497d7b339a684a1a76de3aaccf5269)
1c28749e9Skais /*
2c28749e9Skais  * CDDL HEADER START
3c28749e9Skais  *
4c28749e9Skais  * The contents of this file are subject to the terms of the
5968d6ddeSkrishna  * Common Development and Distribution License (the "License").
6968d6ddeSkrishna  * You may not use this file except in compliance with the License.
7c28749e9Skais  *
8c28749e9Skais  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c28749e9Skais  * or http://www.opensolaris.org/os/licensing.
10c28749e9Skais  * See the License for the specific language governing permissions
11c28749e9Skais  * and limitations under the License.
12c28749e9Skais  *
13c28749e9Skais  * When distributing Covered Code, include this CDDL HEADER in each
14c28749e9Skais  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c28749e9Skais  * If applicable, add the following below this CDDL HEADER, with the
16c28749e9Skais  * fields enclosed by brackets "[]" replaced with your own identifying
17c28749e9Skais  * information: Portions Copyright [yyyy] [name of copyright owner]
18c28749e9Skais  *
19c28749e9Skais  * CDDL HEADER END
20c28749e9Skais  */
21c28749e9Skais /*
2211d0a659SVladimir Kotal  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23c28749e9Skais  */
24c28749e9Skais 
25c28749e9Skais #include <sys/types.h>
26c28749e9Skais #include <sys/stream.h>
27c28749e9Skais #include <sys/strsubr.h>
28c28749e9Skais #include <sys/stropts.h>
29c28749e9Skais #include <sys/strsun.h>
30c28749e9Skais #define	_SUN_TPI_VERSION 2
31c28749e9Skais #include <sys/ddi.h>
32c28749e9Skais #include <sys/sunddi.h>
33c28749e9Skais #include <sys/debug.h>
34c28749e9Skais #include <sys/vtrace.h>
35c28749e9Skais #include <sys/kmem.h>
36c28749e9Skais #include <sys/cpuvar.h>
37c28749e9Skais #include <sys/atomic.h>
38c28749e9Skais #include <sys/sysmacros.h>
39c28749e9Skais 
40c28749e9Skais #include <sys/errno.h>
41c28749e9Skais #include <sys/isa_defs.h>
42c28749e9Skais #include <sys/md5.h>
43c28749e9Skais #include <sys/sha1.h>
44c28749e9Skais #include <sys/random.h>
45c28749e9Skais #include <inet/common.h>
46c28749e9Skais #include <netinet/in.h>
47c28749e9Skais 
48c28749e9Skais #include <sys/systm.h>
49c28749e9Skais #include <sys/param.h>
50c28749e9Skais 
51c28749e9Skais #include "ksslimpl.h"
52c28749e9Skais #include "ksslapi.h"
53c28749e9Skais #include "ksslproto.h"
54c28749e9Skais 
55c28749e9Skais static ssl3CipherSuiteDef cipher_suite_defs[] = {
562bd70d4bSkrishna 	/* 2 X 16 byte keys +  2 x 20 byte MAC secrets, no IVs */
57c28749e9Skais 	{SSL_RSA_WITH_RC4_128_SHA,	cipher_rc4,	mac_sha,	72},
582bd70d4bSkrishna 
592bd70d4bSkrishna 	/* 2 X 16 byte keys +  2 x 16 byte MAC secrets, no IVs */
60c28749e9Skais 	{SSL_RSA_WITH_RC4_128_MD5,	cipher_rc4,	mac_md5,	64},
612bd70d4bSkrishna 
622bd70d4bSkrishna 	/* 2 X 8 byte keys +  2 x 20 byte MAC secrets, 2 x 8 byte IVs */
63c28749e9Skais 	{SSL_RSA_WITH_DES_CBC_SHA,	cipher_des,	mac_sha,	72},
642bd70d4bSkrishna 
652bd70d4bSkrishna 	/* 2 X 24 byte keys +  2 x 20 byte MAC secrets, 2 x 8 byte IVs */
66c28749e9Skais 	{SSL_RSA_WITH_3DES_EDE_CBC_SHA,	cipher_3des,	mac_sha,	104},
672bd70d4bSkrishna 
682bd70d4bSkrishna 	/* 2 X 16 byte keys +  2 x 20 byte MAC secrets, 2 x 16 byte IVs */
692bd70d4bSkrishna 	{TLS_RSA_WITH_AES_128_CBC_SHA,	cipher_aes128,	mac_sha,	104},
702bd70d4bSkrishna 
712bd70d4bSkrishna 	/* 2 X 32 byte keys +  2 x 20 byte MAC secrets, 2 x 16 byte IVs */
722bd70d4bSkrishna 	{TLS_RSA_WITH_AES_256_CBC_SHA,	cipher_aes256,	mac_sha,	136},
732bd70d4bSkrishna 
74c28749e9Skais 	{SSL_RSA_WITH_NULL_SHA,		cipher_null,	mac_sha,	40}
75c28749e9Skais };
76c28749e9Skais 
77c28749e9Skais static int cipher_suite_defs_nentries =
78c28749e9Skais     sizeof (cipher_suite_defs) / sizeof (cipher_suite_defs[0]);
79c28749e9Skais 
80c28749e9Skais static KSSLMACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */
81c28749e9Skais 	/* macsz padsz HashInit HashUpdate HashFinal */
82c28749e9Skais 
83c28749e9Skais 	{MD5_HASH_LEN, SSL3_MD5_PAD_LEN,
84c28749e9Skais 	    (hashinit_func_t)MD5Init, (hashupdate_func_t)MD5Update,
85c28749e9Skais 	    (hashfinal_func_t)MD5Final},
86c28749e9Skais 
87c28749e9Skais 	{SHA1_HASH_LEN, SSL3_SHA1_PAD_LEN,
88c28749e9Skais 	    (hashinit_func_t)SHA1Init, (hashupdate_func_t)SHA1Update,
89c28749e9Skais 	    (hashfinal_func_t)SHA1Final},
90c28749e9Skais };
91c28749e9Skais 
92c28749e9Skais static uchar_t kssl_pad_1[60] = {
93c28749e9Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
94c28749e9Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
95c28749e9Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
96c28749e9Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
97c28749e9Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
98c28749e9Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
99c28749e9Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
100c28749e9Skais     0x36, 0x36, 0x36, 0x36
101c28749e9Skais };
102c28749e9Skais static uchar_t kssl_pad_2[60] = {
103c28749e9Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
104c28749e9Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
105c28749e9Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
106c28749e9Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
107c28749e9Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
108c28749e9Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
109c28749e9Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
110c28749e9Skais     0x5c, 0x5c, 0x5c, 0x5c
111c28749e9Skais };
112c28749e9Skais 
113c28749e9Skais static boolean_t kssl_synchronous = B_FALSE;
114c28749e9Skais 
115c28749e9Skais static void kssl_update_handshake_hashes(ssl_t *, uchar_t *, uint_t);
116c28749e9Skais static int kssl_compute_handshake_hashes(ssl_t *, SSL3Hashes *, uint32_t);
117c28749e9Skais static int kssl_handle_client_hello(ssl_t *, mblk_t *, int);
118c28749e9Skais static int kssl_handle_client_key_exchange(ssl_t *, mblk_t *, int,
119c28749e9Skais     kssl_callback_t, void *);
120c28749e9Skais static int kssl_send_server_hello(ssl_t *);
121c28749e9Skais static int kssl_send_certificate_and_server_hello_done(ssl_t *);
122c28749e9Skais static int kssl_send_change_cipher_specs(ssl_t *);
123c28749e9Skais static int kssl_send_finished(ssl_t *, int);
124c28749e9Skais static int kssl_handle_finished(ssl_t *, mblk_t *, int);
125c28749e9Skais static void kssl_get_hello_random(uchar_t *);
126c28749e9Skais static uchar_t *kssl_rsa_unwrap(uchar_t *, size_t *);
127c28749e9Skais static void kssl_cache_sid(sslSessionID *, kssl_entry_t *);
1282ec7cc7fSKrishna Yenduri static void kssl_lookup_sid(sslSessionID *, uchar_t *, in6_addr_t *,
129c28749e9Skais     kssl_entry_t *);
130c28749e9Skais static int kssl_generate_tls_ms(ssl_t *, uchar_t *, size_t);
131c28749e9Skais static void kssl_generate_ssl_ms(ssl_t *, uchar_t *, size_t);
132c28749e9Skais static int kssl_generate_tls_keyblock(ssl_t *);
133c28749e9Skais static void kssl_generate_keyblock(ssl_t *);
134c28749e9Skais static void kssl_ssl3_key_material_derive_step(ssl_t *, uchar_t *, size_t,
135c28749e9Skais     int, uchar_t *, int);
136c28749e9Skais static int kssl_tls_PRF(ssl_t *, uchar_t *, size_t,
137c28749e9Skais     uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t);
138c28749e9Skais static int kssl_tls_P_hash(crypto_mechanism_t *, crypto_key_t *,
139c28749e9Skais     size_t, uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t);
140c28749e9Skais static void kssl_cke_done(void *, int);
141c28749e9Skais 
142c28749e9Skais #define	HMAC_INIT(m, k, c) \
143c28749e9Skais 	rv = crypto_mac_init(m, k, NULL, c, NULL); if (CRYPTO_ERR(rv)) goto end;
144c28749e9Skais 
145c28749e9Skais #define	HMAC_UPDATE(c, d, l) \
146c28749e9Skais 	dd.cd_raw.iov_base = (char *)d; \
147c28749e9Skais 	dd.cd_length = dd.cd_raw.iov_len = l; \
148c28749e9Skais 	rv = crypto_mac_update(c, &dd, NULL); if (CRYPTO_ERR(rv)) goto end;
149c28749e9Skais 
150c28749e9Skais #define	HMAC_FINAL(c, d, l) \
151c28749e9Skais 	mac.cd_raw.iov_base = (char *)d; \
152c28749e9Skais 	mac.cd_length = mac.cd_raw.iov_len = l; \
153c28749e9Skais 	rv = crypto_mac_final(c, &mac, NULL); if (CRYPTO_ERR(rv)) goto end;
154c28749e9Skais 
155efe05f9eSkrishna /*
156efe05f9eSkrishna  * This hack can go away once we have SSL3 MAC support by KCF
157efe05f9eSkrishna  * software providers (See 4873559).
158efe05f9eSkrishna  */
159efe05f9eSkrishna extern int kcf_md5_threshold;
160efe05f9eSkrishna 
161c28749e9Skais int
162c28749e9Skais kssl_compute_record_mac(
163c28749e9Skais 	ssl_t *ssl,
164c28749e9Skais 	int direction,
165c28749e9Skais 	uint64_t seq_num,
166c28749e9Skais 	SSL3ContentType ct,
167c28749e9Skais 	uchar_t *versionp,
168c28749e9Skais 	uchar_t *buf,
169c28749e9Skais 	int len,
170c28749e9Skais 	uchar_t *digest)
171c28749e9Skais {
172c28749e9Skais 	KSSL_HASHCTX mac_ctx;
173c28749e9Skais 	KSSL_HASHCTX *ctx = &mac_ctx;
174c28749e9Skais 	uchar_t temp[16], *p;
175c28749e9Skais 	KSSLCipherSpec *spec;
176efe05f9eSkrishna 	boolean_t hash_use_ok = B_FALSE;
177c28749e9Skais 	int rv = 0;
178c28749e9Skais 
179c28749e9Skais 	spec = &ssl->spec[direction];
180c28749e9Skais 
181c28749e9Skais 	if (spec->mac_hashsz == 0) {
182c28749e9Skais 		return (1);
183c28749e9Skais 	}
184c28749e9Skais 
185c28749e9Skais 	p = temp;
186c28749e9Skais 
187c28749e9Skais 	*p++ = (seq_num >> 56) & 0xff;
188c28749e9Skais 	*p++ = (seq_num >> 48) & 0xff;
189c28749e9Skais 	*p++ = (seq_num >> 40) & 0xff;
190c28749e9Skais 	*p++ = (seq_num >> 32) & 0xff;
191c28749e9Skais 	*p++ = (seq_num >> 24) & 0xff;
192c28749e9Skais 	*p++ = (seq_num >> 16) & 0xff;
193c28749e9Skais 	*p++ = (seq_num >> 8) & 0xff;
194c28749e9Skais 	*p++ = (seq_num) & 0xff;
195c28749e9Skais 	*p++ = (uchar_t)ct;
196c28749e9Skais 	if (IS_TLS(ssl)) {
197c28749e9Skais 		*p++ = versionp[0];
198c28749e9Skais 		*p++ = versionp[1];
199c28749e9Skais 	}
200c28749e9Skais 	*p++ = (len >> 8) & 0xff;
201c28749e9Skais 	*p++ = (len) & 0xff;
202c28749e9Skais 
203efe05f9eSkrishna 	if (IS_TLS(ssl) || (spec->hmac_mech.cm_type != CRYPTO_MECH_INVALID &&
204efe05f9eSkrishna 	    len >= kcf_md5_threshold)) {
205c28749e9Skais 		crypto_data_t dd, mac;
206efe05f9eSkrishna 		struct uio uio_pt;
207efe05f9eSkrishna 		struct iovec iovarray_pt[2];
208c28749e9Skais 
209efe05f9eSkrishna 		/* init the array of iovecs for use in the uio struct */
210efe05f9eSkrishna 		iovarray_pt[0].iov_base = (char *)temp;
211efe05f9eSkrishna 		iovarray_pt[0].iov_len = (p - temp);
212efe05f9eSkrishna 		iovarray_pt[1].iov_base = (char *)buf;
213efe05f9eSkrishna 		iovarray_pt[1].iov_len = len;
214efe05f9eSkrishna 
215efe05f9eSkrishna 		/* init the uio struct for use in the crypto_data_t struct */
216efe05f9eSkrishna 		bzero(&uio_pt, sizeof (uio_pt));
217efe05f9eSkrishna 		uio_pt.uio_iov = iovarray_pt;
218efe05f9eSkrishna 		uio_pt.uio_iovcnt = 2;
219efe05f9eSkrishna 		uio_pt.uio_segflg = UIO_SYSSPACE;
220efe05f9eSkrishna 
221efe05f9eSkrishna 		dd.cd_format = CRYPTO_DATA_UIO;
222c28749e9Skais 		dd.cd_offset = 0;
223efe05f9eSkrishna 		dd.cd_length =  (p - temp) + len;
224efe05f9eSkrishna 		dd.cd_miscdata = NULL;
225efe05f9eSkrishna 		dd.cd_uio = &uio_pt;
226efe05f9eSkrishna 
227c28749e9Skais 		mac.cd_format = CRYPTO_DATA_RAW;
228c28749e9Skais 		mac.cd_offset = 0;
229efe05f9eSkrishna 		mac.cd_raw.iov_base = (char *)digest;
230efe05f9eSkrishna 		mac.cd_length = mac.cd_raw.iov_len = spec->mac_hashsz;
231c28749e9Skais 
232efe05f9eSkrishna 		/*
233efe05f9eSkrishna 		 * The calling context can tolerate a blocking call here.
234dd49f125SAnders Persson 		 * For outgoing traffic, we are in user context when called
235dd49f125SAnders Persson 		 * from kssl_data_out_cb(). For incoming traffic past the
236dd49f125SAnders Persson 		 * SSL handshake, we are in user context when called from
237dd49f125SAnders Persson 		 * kssl_data_in_proc_cb(). During the SSL handshake, we are
238dd49f125SAnders Persson 		 * called for client_finished message handling from a taskq
239dd49f125SAnders Persson 		 * thread.
240efe05f9eSkrishna 		 */
241efe05f9eSkrishna 		rv = crypto_mac(&spec->hmac_mech, &dd, &spec->hmac_key,
242efe05f9eSkrishna 		    NULL, &mac, NULL);
243efe05f9eSkrishna 
244c28749e9Skais 		if (CRYPTO_ERR(rv)) {
245efe05f9eSkrishna 			hash_use_ok = (rv == CRYPTO_MECH_NOT_SUPPORTED &&
246efe05f9eSkrishna 			    !IS_TLS(ssl));
247efe05f9eSkrishna 			if (!hash_use_ok) {
24851dd2c77Svk199839 				DTRACE_PROBE1(kssl_err__crypto_mac_error,
24951dd2c77Svk199839 				    int, rv);
250c28749e9Skais 				KSSL_COUNTER(compute_mac_failure, 1);
251c28749e9Skais 			}
252efe05f9eSkrishna 		}
253efe05f9eSkrishna 	} else
254efe05f9eSkrishna 		hash_use_ok = B_TRUE;
255efe05f9eSkrishna 
256efe05f9eSkrishna 	if (hash_use_ok) {
257c28749e9Skais 		bcopy(&(ssl->mac_ctx[direction][0]), ctx,
258c28749e9Skais 		    sizeof (KSSL_HASHCTX));
259c28749e9Skais 		spec->MAC_HashUpdate((void *)ctx, temp, p - temp);
260c28749e9Skais 		spec->MAC_HashUpdate((void *)ctx, buf, len);
261c28749e9Skais 		spec->MAC_HashFinal(digest, (void *)ctx);
262c28749e9Skais 
263c28749e9Skais 		bcopy(&(ssl->mac_ctx[direction][1]), ctx,
264c28749e9Skais 		    sizeof (KSSL_HASHCTX));
265c28749e9Skais 		spec->MAC_HashUpdate((void *)ctx, digest, spec->mac_hashsz);
266c28749e9Skais 		spec->MAC_HashFinal(digest, (void *)ctx);
267c28749e9Skais 	}
268c28749e9Skais 
269c28749e9Skais 	return (rv);
270c28749e9Skais }
271c28749e9Skais 
272c28749e9Skais /*
273c28749e9Skais  * Handles handshake messages.
274c28749e9Skais  * Messages to be replied are returned in handshake_sendbuf.
275c28749e9Skais  */
276c28749e9Skais int
277c28749e9Skais kssl_handle_handshake_message(ssl_t *ssl, mblk_t *mp, int *err,
278c28749e9Skais     kssl_callback_t cbfn, void *arg)
279c28749e9Skais {
280c28749e9Skais 	uint32_t msglen;
281c28749e9Skais 	uchar_t msghdr[4];
282c28749e9Skais 
283c28749e9Skais 	ASSERT(ssl->msg.state == MSG_BODY);
284c28749e9Skais 	ASSERT(ssl->msg.msglen_bytes == 3);
285c28749e9Skais 	ASSERT(mp->b_wptr >= mp->b_rptr + ssl->msg.msglen);
286c28749e9Skais 
287c28749e9Skais 	ssl->sslcnt++;
288c28749e9Skais 	msglen = ssl->msg.msglen;
289c28749e9Skais 
290c28749e9Skais 	if (ssl->msg.type == client_hello) {
291c28749e9Skais 		MD5Init(&ssl->hs_md5);
292c28749e9Skais 		SHA1Init(&ssl->hs_sha1);
293c28749e9Skais 	}
294c28749e9Skais 
295c28749e9Skais 	if (ssl->msg.type == finished && ssl->resumed == B_FALSE) {
296c28749e9Skais 		if (kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes,
297c28749e9Skais 		    sender_client) != 0) {
298c28749e9Skais 			*err = SSL_MISS;
299c28749e9Skais 			return (0);
300c28749e9Skais 		}
301c28749e9Skais 	}
302c28749e9Skais 
303c28749e9Skais 	if (ssl->msg.type != finished || ssl->resumed == B_FALSE) {
304c28749e9Skais 		msghdr[0] = (uchar_t)ssl->msg.type;
305c28749e9Skais 
306c28749e9Skais 		msghdr[1] = (uchar_t)(msglen >> 16);
307c28749e9Skais 		msghdr[2] = (uchar_t)(msglen >> 8);
308c28749e9Skais 		msghdr[3] = (uchar_t)(msglen);
309c28749e9Skais 		kssl_update_handshake_hashes(ssl, msghdr, 4);
310c28749e9Skais 		kssl_update_handshake_hashes(ssl, mp->b_rptr, msglen);
311c28749e9Skais 	}
312c28749e9Skais 
313c28749e9Skais 	ssl->msg.state = MSG_INIT;
314c28749e9Skais 	ssl->msg.msglen = 0;
315c28749e9Skais 	ssl->msg.msglen_bytes = 0;
316c28749e9Skais 
317c28749e9Skais 	switch (ssl->msg.type) {
318c28749e9Skais 	case client_hello:
319c28749e9Skais 		if (ssl->hs_waitstate != wait_client_hello) {
320c28749e9Skais 			kssl_send_alert(ssl, alert_fatal,
321c28749e9Skais 			    unexpected_message);
322c28749e9Skais 			*err = EBADMSG;
323c28749e9Skais 			ssl->activeinput = B_FALSE;
324c28749e9Skais 			return (1);
325c28749e9Skais 		}
326c28749e9Skais 		*err = kssl_handle_client_hello(ssl, mp, msglen);
327c28749e9Skais 		if (*err == SSL_MISS) {
328c28749e9Skais 			ssl->activeinput = B_FALSE;
329c28749e9Skais 			return (0);
330c28749e9Skais 		}
331c28749e9Skais 		return (1);
332c28749e9Skais 	case client_key_exchange:
333c28749e9Skais 		if (ssl->hs_waitstate != wait_client_key) {
334c28749e9Skais 			kssl_send_alert(ssl, alert_fatal,
335c28749e9Skais 			    unexpected_message);
336c28749e9Skais 			*err = EBADMSG;
337c28749e9Skais 			ssl->activeinput = B_FALSE;
338c28749e9Skais 			return (1);
339c28749e9Skais 		}
340c28749e9Skais 		*err = kssl_handle_client_key_exchange(ssl, mp,
341c28749e9Skais 		    msglen, cbfn, arg);
342c28749e9Skais 		return (1);
343c28749e9Skais 	case finished:
344c28749e9Skais 		if (ssl->hs_waitstate != wait_finished) {
345c28749e9Skais 			kssl_send_alert(ssl, alert_fatal,
346c28749e9Skais 			    unexpected_message);
347c28749e9Skais 			*err = EBADMSG;
348c28749e9Skais 			ssl->activeinput = B_FALSE;
349c28749e9Skais 			return (1);
350c28749e9Skais 		}
351c28749e9Skais 		*err = kssl_handle_finished(ssl, mp, msglen);
352c28749e9Skais 		return (1);
353c28749e9Skais 	default:
354c28749e9Skais 		kssl_send_alert(ssl, alert_fatal, unexpected_message);
355c28749e9Skais 		ssl->activeinput = B_FALSE;
356c28749e9Skais 		*err = EBADMSG;
357c28749e9Skais 		return (1);
358c28749e9Skais 	}
359c28749e9Skais }
360c28749e9Skais 
361c28749e9Skais static void
362c28749e9Skais kssl_update_handshake_hashes(ssl_t *ssl, uchar_t *buf, uint_t len)
363c28749e9Skais {
364c28749e9Skais 	MD5Update(&ssl->hs_md5, buf, len);
365c28749e9Skais 	SHA1Update(&ssl->hs_sha1, buf, len);
366c28749e9Skais }
367c28749e9Skais 
368c28749e9Skais static int
369c28749e9Skais kssl_compute_handshake_hashes(
370c28749e9Skais 	ssl_t *ssl,
371c28749e9Skais 	SSL3Hashes *hashes,
372c28749e9Skais 	uint32_t sender)
373c28749e9Skais {
374c28749e9Skais 	MD5_CTX md5 = ssl->hs_md5;	/* clone md5 context */
375c28749e9Skais 	SHA1_CTX sha1 = ssl->hs_sha1;	/* clone sha1 context */
376c28749e9Skais 	MD5_CTX *md5ctx = &md5;
377c28749e9Skais 	SHA1_CTX *sha1ctx = &sha1;
378c28749e9Skais 
379c28749e9Skais 	if (IS_TLS(ssl)) {
380c28749e9Skais 		uchar_t seed[MD5_HASH_LEN + SHA1_HASH_LEN];
381c28749e9Skais 		char *label;
382c28749e9Skais 
383c28749e9Skais 		/*
384c28749e9Skais 		 * Do not take another hash step here.
385c28749e9Skais 		 * Just complete the operation.
386c28749e9Skais 		 */
387c28749e9Skais 		MD5Final(hashes->md5, md5ctx);
388c28749e9Skais 		SHA1Final(hashes->sha1, sha1ctx);
389c28749e9Skais 
390c28749e9Skais 		bcopy(hashes->md5, seed, MD5_HASH_LEN);
391c28749e9Skais 		bcopy(hashes->sha1, seed + MD5_HASH_LEN, SHA1_HASH_LEN);
392c28749e9Skais 
393c28749e9Skais 		if (sender == sender_client)
394c28749e9Skais 			label = TLS_CLIENT_FINISHED_LABEL;
395c28749e9Skais 		else
396c28749e9Skais 			label = TLS_SERVER_FINISHED_LABEL;
397c28749e9Skais 
398c28749e9Skais 		return (kssl_tls_PRF(ssl,
39951dd2c77Svk199839 		    ssl->sid.master_secret,
40051dd2c77Svk199839 		    (size_t)SSL3_MASTER_SECRET_LEN,
401c28749e9Skais 		    (uchar_t *)label, strlen(label),
402c28749e9Skais 		    seed, (size_t)(MD5_HASH_LEN + SHA1_HASH_LEN),
403c28749e9Skais 		    hashes->tlshash, (size_t)TLS_FINISHED_SIZE));
404c28749e9Skais 	} else {
405c28749e9Skais 		uchar_t s[4];
406c28749e9Skais 		s[0] = (sender >> 24) & 0xff;
407c28749e9Skais 		s[1] = (sender >> 16) & 0xff;
408c28749e9Skais 		s[2] = (sender >> 8) & 0xff;
409c28749e9Skais 		s[3] = (sender) & 0xff;
410c28749e9Skais 
411c28749e9Skais 		MD5Update(md5ctx, s, 4);
412c28749e9Skais 		MD5Update(md5ctx, ssl->sid.master_secret,
413c28749e9Skais 		    SSL3_MASTER_SECRET_LEN);
414c28749e9Skais 		MD5Update(md5ctx, kssl_pad_1, SSL3_MD5_PAD_LEN);
415c28749e9Skais 		MD5Final(hashes->md5, md5ctx);
416c28749e9Skais 
417c28749e9Skais 		MD5Init(md5ctx);
418c28749e9Skais 		MD5Update(md5ctx, ssl->sid.master_secret,
419c28749e9Skais 		    SSL3_MASTER_SECRET_LEN);
420c28749e9Skais 		MD5Update(md5ctx, kssl_pad_2, SSL3_MD5_PAD_LEN);
421c28749e9Skais 		MD5Update(md5ctx, hashes->md5, MD5_HASH_LEN);
422c28749e9Skais 		MD5Final(hashes->md5, md5ctx);
423c28749e9Skais 
424c28749e9Skais 		SHA1Update(sha1ctx, s, 4);
425c28749e9Skais 		SHA1Update(sha1ctx, ssl->sid.master_secret,
426c28749e9Skais 		    SSL3_MASTER_SECRET_LEN);
427c28749e9Skais 		SHA1Update(sha1ctx, kssl_pad_1, SSL3_SHA1_PAD_LEN);
428c28749e9Skais 		SHA1Final(hashes->sha1, sha1ctx);
429c28749e9Skais 
430c28749e9Skais 		SHA1Init(sha1ctx);
431c28749e9Skais 		SHA1Update(sha1ctx, ssl->sid.master_secret,
432c28749e9Skais 		    SSL3_MASTER_SECRET_LEN);
433c28749e9Skais 		SHA1Update(sha1ctx, kssl_pad_2, SSL3_SHA1_PAD_LEN);
434c28749e9Skais 		SHA1Update(sha1ctx, hashes->sha1, SHA1_HASH_LEN);
435c28749e9Skais 		SHA1Final(hashes->sha1, sha1ctx);
436c28749e9Skais 		return (0);
437c28749e9Skais 	}
438c28749e9Skais }
439c28749e9Skais 
440c28749e9Skais 
44151144063SKrishna Yenduri /*
44251144063SKrishna Yenduri  * Minimum message length for a client hello =
44351144063SKrishna Yenduri  * 2-byte client_version +
44451144063SKrishna Yenduri  * 32-byte random +
44551144063SKrishna Yenduri  * 1-byte session_id length +
44651144063SKrishna Yenduri  * 2-byte cipher_suites length +
44751144063SKrishna Yenduri  * 1-byte compression_methods length +
44851144063SKrishna Yenduri  * 1-byte CompressionMethod.null
44951144063SKrishna Yenduri  */
450c28749e9Skais #define	KSSL_SSL3_CH_MIN_MSGLEN	(39)
451c28749e9Skais 
45265d18457SVladimir Kotal /*
45365d18457SVladimir Kotal  * Process SSL/TLS Client Hello message. Return 0 on success, errno value
45465d18457SVladimir Kotal  * or SSL_MISS if no cipher suite of the server matches the list received
45565d18457SVladimir Kotal  * in the message.
45665d18457SVladimir Kotal  */
457c28749e9Skais static int
458c28749e9Skais kssl_handle_client_hello(ssl_t *ssl, mblk_t *mp, int msglen)
459c28749e9Skais {
460c28749e9Skais 	uchar_t *msgend;
461c28749e9Skais 	int err;
462c28749e9Skais 	SSL3AlertDescription desc = illegal_parameter;
46351144063SKrishna Yenduri 	uint_t sidlen, cslen, cmlen;
464c28749e9Skais 	uchar_t *suitesp;
465c28749e9Skais 	uint_t i, j;
46611d0a659SVladimir Kotal 	uint16_t suite, selected_suite;
467c28749e9Skais 	int ch_msglen = KSSL_SSL3_CH_MIN_MSGLEN;
46811d0a659SVladimir Kotal 	boolean_t suite_found = B_FALSE;
469c28749e9Skais 
470c28749e9Skais 	ASSERT(mp->b_wptr >= mp->b_rptr + msglen);
471c28749e9Skais 	ASSERT(ssl->msg.type == client_hello);
472c28749e9Skais 	ASSERT(ssl->hs_waitstate == wait_client_hello);
473c28749e9Skais 	ASSERT(ssl->resumed == B_FALSE);
474c28749e9Skais 
475c28749e9Skais 	if (msglen < ch_msglen) {
47665d18457SVladimir Kotal 		DTRACE_PROBE2(kssl_err__msglen_less_than_minimum,
47765d18457SVladimir Kotal 		    int, msglen, int, ch_msglen);
478c28749e9Skais 		goto falert;
479c28749e9Skais 	}
480c28749e9Skais 
481c28749e9Skais 	msgend = mp->b_rptr + msglen;
482c28749e9Skais 
483c28749e9Skais 	/* Support SSLv3 (version == 3.0) or TLS (version == 3.1) */
484c28749e9Skais 	if (ssl->major_version != 3 || (ssl->major_version == 3 &&
485c28749e9Skais 	    ssl->minor_version != 0 && ssl->minor_version != 1)) {
48651dd2c77Svk199839 		DTRACE_PROBE2(kssl_err__SSL_version_not_supported,
48751dd2c77Svk199839 		    uchar_t, ssl->major_version,
48851dd2c77Svk199839 		    uchar_t, ssl->minor_version);
489c28749e9Skais 		desc = handshake_failure;
490c28749e9Skais 		goto falert;
491c28749e9Skais 	}
492c28749e9Skais 	mp->b_rptr += 2; /* skip the version bytes */
493c28749e9Skais 
49465d18457SVladimir Kotal 	/* read client random field */
495c28749e9Skais 	bcopy(mp->b_rptr, ssl->client_random, SSL3_RANDOM_LENGTH);
496c28749e9Skais 	mp->b_rptr += SSL3_RANDOM_LENGTH;
497c28749e9Skais 
49865d18457SVladimir Kotal 	/* read session ID length */
499c28749e9Skais 	ASSERT(ssl->sid.cached == B_FALSE);
500c28749e9Skais 	sidlen = *mp->b_rptr++;
501c28749e9Skais 	ch_msglen += sidlen;
502c28749e9Skais 	if (msglen < ch_msglen) {
50365d18457SVladimir Kotal 		DTRACE_PROBE2(kssl_err__invalid_message_length_after_ver,
50465d18457SVladimir Kotal 		    int, msglen, int, ch_msglen);
505c28749e9Skais 		goto falert;
506c28749e9Skais 	}
507c28749e9Skais 	if (sidlen != SSL3_SESSIONID_BYTES) {
508c28749e9Skais 		mp->b_rptr += sidlen;
509c28749e9Skais 	} else {
5102ec7cc7fSKrishna Yenduri 		kssl_lookup_sid(&ssl->sid, mp->b_rptr, &ssl->faddr,
511c28749e9Skais 		    ssl->kssl_entry);
512c28749e9Skais 		mp->b_rptr += SSL3_SESSIONID_BYTES;
513c28749e9Skais 	}
514c28749e9Skais 
51565d18457SVladimir Kotal 	/* read cipher suite length */
51651144063SKrishna Yenduri 	cslen = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1];
517c28749e9Skais 	mp->b_rptr += 2;
51851144063SKrishna Yenduri 	ch_msglen += cslen;
51951144063SKrishna Yenduri 
52051144063SKrishna Yenduri 	/*
52151144063SKrishna Yenduri 	 * This check can't be a "!=" since there can be
52251144063SKrishna Yenduri 	 * compression methods other than CompressionMethod.null.
52351144063SKrishna Yenduri 	 * Also, there can be extra data (TLS extensions) after the
52411d0a659SVladimir Kotal 	 * compression methods field.
52551144063SKrishna Yenduri 	 */
52651144063SKrishna Yenduri 	if (msglen < ch_msglen) {
52765d18457SVladimir Kotal 		DTRACE_PROBE2(kssl_err__invalid_message_length_after_cslen,
52865d18457SVladimir Kotal 		    int, msglen, int, ch_msglen);
529c28749e9Skais 		goto falert;
530c28749e9Skais 	}
53151144063SKrishna Yenduri 
53211d0a659SVladimir Kotal 	/* The length has to be even since a cipher suite is 2-byte long. */
53351144063SKrishna Yenduri 	if (cslen & 0x1) {
53465d18457SVladimir Kotal 		DTRACE_PROBE1(kssl_err__uneven_cipher_suite_length,
53565d18457SVladimir Kotal 		    uint_t, cslen);
536c28749e9Skais 		goto falert;
537c28749e9Skais 	}
538c28749e9Skais 	suitesp = mp->b_rptr;
53911d0a659SVladimir Kotal 
54011d0a659SVladimir Kotal 	/* session resumption checks */
541c28749e9Skais 	if (ssl->sid.cached == B_TRUE) {
542c28749e9Skais 		suite = ssl->sid.cipher_suite;
54351144063SKrishna Yenduri 		for (j = 0; j < cslen; j += 2) {
54411d0a659SVladimir Kotal 			DTRACE_PROBE2(kssl_cipher_suite_check_resumpt,
54511d0a659SVladimir Kotal 			    uint16_t, suite,
54611d0a659SVladimir Kotal 			    uint16_t,
54711d0a659SVladimir Kotal 			    (uint16_t)((suitesp[j] << 8) + suitesp[j+1]));
54811d0a659SVladimir Kotal 			/* Check for regular (true) cipher suite. */
549c28749e9Skais 			if (suitesp[j] == ((suite >> 8) & 0xff) &&
550c28749e9Skais 			    suitesp[j + 1] == (suite & 0xff)) {
55111d0a659SVladimir Kotal 				DTRACE_PROBE1(kssl_cipher_suite_found_resumpt,
55211d0a659SVladimir Kotal 				    uint16_t, suite);
55311d0a659SVladimir Kotal 				suite_found = B_TRUE;
55411d0a659SVladimir Kotal 				selected_suite = suite;
55511d0a659SVladimir Kotal 			}
55611d0a659SVladimir Kotal 
55711d0a659SVladimir Kotal 			/* Check for SCSV. */
55811d0a659SVladimir Kotal 			if (suitesp[j] ==  ((SSL_SCSV >> 8) & 0xff) &&
55911d0a659SVladimir Kotal 			    suitesp[j + 1] == (SSL_SCSV & 0xff)) {
56011d0a659SVladimir Kotal 				DTRACE_PROBE(kssl_scsv_found_resumpt);
56111d0a659SVladimir Kotal 				ssl->secure_renegotiation = B_TRUE;
56211d0a659SVladimir Kotal 			}
56311d0a659SVladimir Kotal 
56411d0a659SVladimir Kotal 			/*
56511d0a659SVladimir Kotal 			 * If we got cipher suite match and SCSV we can
56611d0a659SVladimir Kotal 			 * terminate the cycle now.
56711d0a659SVladimir Kotal 			 */
56811d0a659SVladimir Kotal 			if (suite_found && ssl->secure_renegotiation)
569c28749e9Skais 				break;
570c28749e9Skais 		}
57111d0a659SVladimir Kotal 		if (suite_found)
572c28749e9Skais 			goto suite_found;
573c28749e9Skais 		kssl_uncache_sid(&ssl->sid, ssl->kssl_entry);
574c28749e9Skais 	}
575c28749e9Skais 
57611d0a659SVladimir Kotal 	/* Check if this server is capable of the cipher suite. */
577c28749e9Skais 	for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) {
578c28749e9Skais 		suite = ssl->kssl_entry->kssl_cipherSuites[i];
57951144063SKrishna Yenduri 		for (j = 0; j < cslen; j += 2) {
58011d0a659SVladimir Kotal 			DTRACE_PROBE2(kssl_cipher_suite_check, uint16_t, suite,
58111d0a659SVladimir Kotal 			    uint16_t,
58211d0a659SVladimir Kotal 			    (uint16_t)((suitesp[j] << 8) + suitesp[j+1]));
58311d0a659SVladimir Kotal 			/* Check for regular (true) cipher suite. */
584c28749e9Skais 			if (suitesp[j] == ((suite >> 8) & 0xff) &&
585c28749e9Skais 			    suitesp[j + 1] == (suite & 0xff)) {
58611d0a659SVladimir Kotal 				DTRACE_PROBE1(kssl_cipher_suite_found,
58711d0a659SVladimir Kotal 				    uint16_t, suite);
58811d0a659SVladimir Kotal 				suite_found = B_TRUE;
58911d0a659SVladimir Kotal 				selected_suite = suite;
59011d0a659SVladimir Kotal 			}
59111d0a659SVladimir Kotal 
59211d0a659SVladimir Kotal 			/* Check for SCSV. */
59311d0a659SVladimir Kotal 			if (suitesp[j] ==  ((SSL_SCSV >> 8) & 0xff) &&
59411d0a659SVladimir Kotal 			    suitesp[j + 1] == (SSL_SCSV & 0xff)) {
59511d0a659SVladimir Kotal 				DTRACE_PROBE(kssl_scsv_found);
59611d0a659SVladimir Kotal 				ssl->secure_renegotiation = B_TRUE;
59711d0a659SVladimir Kotal 			}
59811d0a659SVladimir Kotal 
59911d0a659SVladimir Kotal 			/*
60011d0a659SVladimir Kotal 			 * If we got cipher suite match and SCSV or went
60111d0a659SVladimir Kotal 			 * through the whole list of client cipher suites
60211d0a659SVladimir Kotal 			 * (hence we know if SCSV was present or not) we
60311d0a659SVladimir Kotal 			 * can terminate the cycle now.
60411d0a659SVladimir Kotal 			 */
60511d0a659SVladimir Kotal 			if (suite_found &&
60611d0a659SVladimir Kotal 			    (ssl->secure_renegotiation || (i > 0)))
607c28749e9Skais 				break;
608c28749e9Skais 		}
60911d0a659SVladimir Kotal 		if (suite_found)
610c28749e9Skais 			break;
611c28749e9Skais 	}
61211d0a659SVladimir Kotal 	if (!suite_found) {
613c28749e9Skais 		if (ssl->sslcnt == 1) {
61465d18457SVladimir Kotal 			DTRACE_PROBE(kssl_no_cipher_suite_found);
615c28749e9Skais 			KSSL_COUNTER(no_suite_found, 1);
61665d18457SVladimir Kotal 			/*
61765d18457SVladimir Kotal 			 * If there is no fallback point terminate the
61865d18457SVladimir Kotal 			 * handshake with SSL alert otherwise return with
61965d18457SVladimir Kotal 			 * SSL_MISS.
62065d18457SVladimir Kotal 			 */
62165d18457SVladimir Kotal 			if (ssl->kssl_entry->ke_fallback_head == NULL) {
62265d18457SVladimir Kotal 				DTRACE_PROBE(kssl_no_fallback);
62365d18457SVladimir Kotal 				desc = handshake_failure;
62465d18457SVladimir Kotal 				goto falert;
62565d18457SVladimir Kotal 			} else {
626c28749e9Skais 				return (SSL_MISS);
627c28749e9Skais 			}
62865d18457SVladimir Kotal 		}
629c28749e9Skais 		desc = handshake_failure;
63051dd2c77Svk199839 		DTRACE_PROBE(kssl_err__no_cipher_suites_found);
631c28749e9Skais 		goto falert;
632c28749e9Skais 	}
633c28749e9Skais 
634c28749e9Skais suite_found:
63551144063SKrishna Yenduri 	mp->b_rptr += cslen;
636c28749e9Skais 
63751144063SKrishna Yenduri 	/*
63851144063SKrishna Yenduri 	 * Check for the mandatory CompressionMethod.null. We do not
63951144063SKrishna Yenduri 	 * support any other compression methods.
64051144063SKrishna Yenduri 	 */
64151144063SKrishna Yenduri 	cmlen = *mp->b_rptr++;
64251144063SKrishna Yenduri 	ch_msglen += cmlen - 1;	/* -1 accounts for the null method */
64351144063SKrishna Yenduri 	if (msglen < ch_msglen) {
64465d18457SVladimir Kotal 		DTRACE_PROBE2(kssl_err__invalid_message_length_after_complen,
64565d18457SVladimir Kotal 		    int, msglen, int, ch_msglen);
64651144063SKrishna Yenduri 		goto falert;
64751144063SKrishna Yenduri 	}
64851144063SKrishna Yenduri 
64965d18457SVladimir Kotal 	/*
65065d18457SVladimir Kotal 	 * Search for null compression method (encoded as 0 byte) in the
65165d18457SVladimir Kotal 	 * compression methods field.
65265d18457SVladimir Kotal 	 */
65351144063SKrishna Yenduri 	while (cmlen >= 1) {
65451144063SKrishna Yenduri 		if (*mp->b_rptr++ == 0)
65551144063SKrishna Yenduri 			break;
65651144063SKrishna Yenduri 		cmlen--;
65751144063SKrishna Yenduri 	}
65851144063SKrishna Yenduri 
65951144063SKrishna Yenduri 	if (cmlen == 0) {
660c28749e9Skais 		desc = handshake_failure;
66165d18457SVladimir Kotal 		DTRACE_PROBE(kssl_err__no_null_compression_method);
662c28749e9Skais 		goto falert;
663c28749e9Skais 	}
664c28749e9Skais 
66511d0a659SVladimir Kotal 	/* Find the suite in the internal cipher suite table. */
666c28749e9Skais 	for (i = 0; i < cipher_suite_defs_nentries; i++) {
66711d0a659SVladimir Kotal 		if (selected_suite == cipher_suite_defs[i].suite) {
668c28749e9Skais 			break;
669c28749e9Skais 		}
670c28749e9Skais 	}
671c28749e9Skais 
67211d0a659SVladimir Kotal 	/* Get past the remaining compression methods (minus null method). */
67311d0a659SVladimir Kotal 	mp->b_rptr += cmlen - 1;
67411d0a659SVladimir Kotal 
675c28749e9Skais 	ASSERT(i < cipher_suite_defs_nentries);
676c28749e9Skais 
67711d0a659SVladimir Kotal 	ssl->pending_cipher_suite = selected_suite;
678c28749e9Skais 	ssl->pending_malg = cipher_suite_defs[i].malg;
679c28749e9Skais 	ssl->pending_calg = cipher_suite_defs[i].calg;
680c28749e9Skais 	ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz;
681c28749e9Skais 
68211d0a659SVladimir Kotal 	/* Parse TLS extensions (if any). */
68311d0a659SVladimir Kotal 	if (ch_msglen + 2 < msglen) {
68411d0a659SVladimir Kotal 		/* Get the length of the extensions. */
68511d0a659SVladimir Kotal 		uint16_t ext_total_len = ((uint_t)mp->b_rptr[0] << 8) +
68611d0a659SVladimir Kotal 		    (uint_t)mp->b_rptr[1];
68711d0a659SVladimir Kotal 		DTRACE_PROBE1(kssl_total_length_extensions, uint16_t,
68811d0a659SVladimir Kotal 		    ext_total_len);
68911d0a659SVladimir Kotal 		/*
69011d0a659SVladimir Kotal 		 * Consider zero extensions length as invalid extension
69111d0a659SVladimir Kotal 		 * encoding.
69211d0a659SVladimir Kotal 		 */
69311d0a659SVladimir Kotal 		if (ext_total_len == 0) {
69411d0a659SVladimir Kotal 			DTRACE_PROBE1(kssl_err__zero_extensions_length,
69511d0a659SVladimir Kotal 			    mblk_t *, mp);
69611d0a659SVladimir Kotal 			goto falert;
69711d0a659SVladimir Kotal 		}
69811d0a659SVladimir Kotal 		ch_msglen += 2;
69911d0a659SVladimir Kotal 		if (ch_msglen + ext_total_len > msglen) {
70011d0a659SVladimir Kotal 			DTRACE_PROBE2(kssl_err__invalid_extensions_length,
70111d0a659SVladimir Kotal 			    int, msglen, int, ch_msglen);
70211d0a659SVladimir Kotal 			goto falert;
70311d0a659SVladimir Kotal 		}
70411d0a659SVladimir Kotal 		mp->b_rptr += 2;
70511d0a659SVladimir Kotal 
70611d0a659SVladimir Kotal 		/*
70711d0a659SVladimir Kotal 		 * Go through the TLS extensions. This is only done to check
70811d0a659SVladimir Kotal 		 * for the presence of renegotiation_info extension. We do not
70911d0a659SVladimir Kotal 		 * support any other TLS extensions and hence ignore them.
71011d0a659SVladimir Kotal 		 */
71111d0a659SVladimir Kotal 		while (mp->b_rptr < msgend) {
71211d0a659SVladimir Kotal 			uint16_t ext_len, ext_type;
71311d0a659SVladimir Kotal 
71411d0a659SVladimir Kotal 			/*
71511d0a659SVladimir Kotal 			 * Check that the extension has at least type and
71611d0a659SVladimir Kotal 			 * length (2 + 2 bytes).
71711d0a659SVladimir Kotal 			 */
71811d0a659SVladimir Kotal 			if (ch_msglen + 4 > msglen) {
71911d0a659SVladimir Kotal 				DTRACE_PROBE(kssl_err__invalid_ext_format);
72011d0a659SVladimir Kotal 				goto falert;
72111d0a659SVladimir Kotal 			}
72211d0a659SVladimir Kotal 
72311d0a659SVladimir Kotal 			/* Get extension type and length */
72411d0a659SVladimir Kotal 			ext_type = ((uint_t)mp->b_rptr[0] << 8) +
72511d0a659SVladimir Kotal 			    (uint_t)mp->b_rptr[1];
72611d0a659SVladimir Kotal 			mp->b_rptr += 2;
72711d0a659SVladimir Kotal 			ext_len = ((uint_t)mp->b_rptr[0] << 8) +
72811d0a659SVladimir Kotal 			    (uint_t)mp->b_rptr[1];
72911d0a659SVladimir Kotal 			mp->b_rptr += 2;
73011d0a659SVladimir Kotal 			ch_msglen += 4;
73111d0a659SVladimir Kotal 			DTRACE_PROBE3(kssl_ext_detected, uint16_t, ext_type,
73211d0a659SVladimir Kotal 			    uint16_t, ext_len, mblk_t *, mp);
73311d0a659SVladimir Kotal 
73411d0a659SVladimir Kotal 			/*
73511d0a659SVladimir Kotal 			 * Make sure the contents of the extension are
73611d0a659SVladimir Kotal 			 * accessible.
73711d0a659SVladimir Kotal 			 */
73811d0a659SVladimir Kotal 			if (ch_msglen + ext_len > msglen) {
73911d0a659SVladimir Kotal 				DTRACE_PROBE1(
74011d0a659SVladimir Kotal 				    kssl_err__invalid_ext_len,
74111d0a659SVladimir Kotal 				    uint16_t, ext_len);
74211d0a659SVladimir Kotal 				goto falert;
74311d0a659SVladimir Kotal 			}
74411d0a659SVladimir Kotal 
74511d0a659SVladimir Kotal 			switch (ext_type) {
74611d0a659SVladimir Kotal 			case TLSEXT_RENEGOTIATION_INFO:
74711d0a659SVladimir Kotal 				/*
74811d0a659SVladimir Kotal 				 * Search for empty "renegotiation_info"
74911d0a659SVladimir Kotal 				 * extension (encoded as ff 01 00 01 00).
75011d0a659SVladimir Kotal 				 */
75111d0a659SVladimir Kotal 				DTRACE_PROBE(kssl_reneg_info_found);
75211d0a659SVladimir Kotal 				if ((ext_len != 1) ||
75311d0a659SVladimir Kotal 				    (*mp->b_rptr != 0)) {
75411d0a659SVladimir Kotal 					DTRACE_PROBE2(
75511d0a659SVladimir Kotal 					    kssl_err__non_empty_reneg_info,
75611d0a659SVladimir Kotal 					    uint16_t, ext_len,
75711d0a659SVladimir Kotal 					    mblk_t *, mp);
75811d0a659SVladimir Kotal 					goto falert;
75911d0a659SVladimir Kotal 				}
76011d0a659SVladimir Kotal 				ssl->secure_renegotiation = B_TRUE;
76111d0a659SVladimir Kotal 				break;
76211d0a659SVladimir Kotal 			default:
76311d0a659SVladimir Kotal 				/* FALLTHRU */
76411d0a659SVladimir Kotal 				break;
76511d0a659SVladimir Kotal 			}
76611d0a659SVladimir Kotal 
76711d0a659SVladimir Kotal 			/* jump to the next extension */
76811d0a659SVladimir Kotal 			ch_msglen += ext_len;
76911d0a659SVladimir Kotal 			mp->b_rptr += ext_len;
77011d0a659SVladimir Kotal 		}
77111d0a659SVladimir Kotal 	}
77211d0a659SVladimir Kotal 
77311d0a659SVladimir Kotal 	mp->b_rptr = msgend;
77411d0a659SVladimir Kotal 
775c28749e9Skais 	if (ssl->sid.cached == B_TRUE) {
776c28749e9Skais 		err = kssl_send_server_hello(ssl);
777c28749e9Skais 		if (err != 0) {
778c28749e9Skais 			return (err);
779c28749e9Skais 		}
780c28749e9Skais 		if (IS_TLS(ssl))
781c28749e9Skais 			err = kssl_generate_tls_keyblock(ssl);
782c28749e9Skais 		else
783c28749e9Skais 			kssl_generate_keyblock(ssl);
784c28749e9Skais 
785c28749e9Skais 		err = kssl_send_change_cipher_specs(ssl);
786c28749e9Skais 		if (err != 0) {
787c28749e9Skais 			return (err);
788c28749e9Skais 		}
789c28749e9Skais 
790c28749e9Skais 		err = kssl_send_finished(ssl, 1);
791c28749e9Skais 		if (err != 0)
792c28749e9Skais 			return (err);
793c28749e9Skais 
794c28749e9Skais 		err = kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes,
795c28749e9Skais 		    sender_client);
796c28749e9Skais 		if (err != 0)
797c28749e9Skais 			return (err);
798c28749e9Skais 
799c28749e9Skais 		ssl->hs_waitstate = wait_change_cipher;
800c28749e9Skais 		ssl->resumed = B_TRUE;
801c28749e9Skais 		ssl->activeinput = B_FALSE;
802c28749e9Skais 		KSSL_COUNTER(resumed_sessions, 1);
803c28749e9Skais 		return (0);
804c28749e9Skais 	}
805c28749e9Skais 
806c28749e9Skais 	(void) random_get_pseudo_bytes(ssl->sid.session_id,
807c28749e9Skais 	    SSL3_SESSIONID_BYTES);
808c28749e9Skais 	ssl->sid.client_addr = ssl->faddr;
80911d0a659SVladimir Kotal 	ssl->sid.cipher_suite = selected_suite;
810c28749e9Skais 
811c28749e9Skais 	err = kssl_send_server_hello(ssl);
812c28749e9Skais 	if (err != 0) {
813c28749e9Skais 		return (err);
814c28749e9Skais 	}
815c28749e9Skais 	err = kssl_send_certificate_and_server_hello_done(ssl);
816c28749e9Skais 	if (err != 0) {
817c28749e9Skais 		return (err);
818c28749e9Skais 	}
819c28749e9Skais 	KSSL_COUNTER(full_handshakes, 1);
820c28749e9Skais 	ssl->hs_waitstate = wait_client_key;
821c28749e9Skais 	ssl->activeinput = B_FALSE;
822c28749e9Skais 	return (0);
823c28749e9Skais 
824c28749e9Skais falert:
825c28749e9Skais 	kssl_send_alert(ssl, alert_fatal, desc);
826c28749e9Skais 	return (EBADMSG);
827c28749e9Skais }
828c28749e9Skais 
8292ec7cc7fSKrishna Yenduri #define	SET_HASH_INDEX(index, s, clnt_addr) {				\
8302ec7cc7fSKrishna Yenduri 	int addr;							\
8312ec7cc7fSKrishna Yenduri 									\
8322ec7cc7fSKrishna Yenduri 	IN6_V4MAPPED_TO_IPADDR(clnt_addr, addr);			\
8332ec7cc7fSKrishna Yenduri 	index = addr ^ (((int)(s)[0] << 24) | ((int)(s)[1] << 16) |	\
8342ec7cc7fSKrishna Yenduri 	    ((int)(s)[2] << 8) | (int)(s)[SSL3_SESSIONID_BYTES - 1]);	\
8352ec7cc7fSKrishna Yenduri }
8362ec7cc7fSKrishna Yenduri 
8372ec7cc7fSKrishna Yenduri /*
8382ec7cc7fSKrishna Yenduri  * Creates a cache entry. Sets the sid->cached flag
8392ec7cc7fSKrishna Yenduri  * and sid->time fields. So, the caller should not set them.
8402ec7cc7fSKrishna Yenduri  */
841c28749e9Skais static void
842c28749e9Skais kssl_cache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry)
843c28749e9Skais {
844c28749e9Skais 	uint_t index;
845c28749e9Skais 	uchar_t *s = sid->session_id;
846c28749e9Skais 	kmutex_t *lock;
847c28749e9Skais 
8482ec7cc7fSKrishna Yenduri 	ASSERT(sid->cached == B_FALSE);
849c28749e9Skais 
8502ec7cc7fSKrishna Yenduri 	/* set the values before creating the cache entry */
8512ec7cc7fSKrishna Yenduri 	sid->cached = B_TRUE;
852d3d50737SRafael Vanoni 	sid->time = ddi_get_lbolt();
853c28749e9Skais 
8542ec7cc7fSKrishna Yenduri 	SET_HASH_INDEX(index, s, &sid->client_addr);
8552ec7cc7fSKrishna Yenduri 	index %= kssl_entry->sid_cache_nentries;
8562ec7cc7fSKrishna Yenduri 
857c28749e9Skais 	lock = &(kssl_entry->sid_cache[index].se_lock);
858c28749e9Skais 	mutex_enter(lock);
859c28749e9Skais 	kssl_entry->sid_cache[index].se_used++;
860c28749e9Skais 	bcopy(sid, &(kssl_entry->sid_cache[index].se_sid), sizeof (*sid));
861c28749e9Skais 	mutex_exit(lock);
8622ec7cc7fSKrishna Yenduri 
8632ec7cc7fSKrishna Yenduri 	KSSL_COUNTER(sid_cached, 1);
864c28749e9Skais }
865c28749e9Skais 
8662ec7cc7fSKrishna Yenduri /*
8672ec7cc7fSKrishna Yenduri  * Invalidates the cache entry, if any. Clears the sid->cached flag
8682ec7cc7fSKrishna Yenduri  * as a side effect.
8692ec7cc7fSKrishna Yenduri  */
8702ec7cc7fSKrishna Yenduri void
8712ec7cc7fSKrishna Yenduri kssl_uncache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry)
872c28749e9Skais {
873c28749e9Skais 	uint_t index;
8742ec7cc7fSKrishna Yenduri 	uchar_t *s = sid->session_id;
875c28749e9Skais 	sslSessionID *csid;
8762ec7cc7fSKrishna Yenduri 	kmutex_t *lock;
877c28749e9Skais 
8782ec7cc7fSKrishna Yenduri 	ASSERT(sid->cached == B_TRUE);
8792ec7cc7fSKrishna Yenduri 	sid->cached = B_FALSE;
880c28749e9Skais 
8812ec7cc7fSKrishna Yenduri 	SET_HASH_INDEX(index, s, &sid->client_addr);
882c28749e9Skais 	index %= kssl_entry->sid_cache_nentries;
883c28749e9Skais 
884c28749e9Skais 	lock = &(kssl_entry->sid_cache[index].se_lock);
885c28749e9Skais 	mutex_enter(lock);
886c28749e9Skais 	csid = &(kssl_entry->sid_cache[index].se_sid);
8872ec7cc7fSKrishna Yenduri 	if (!(IN6_ARE_ADDR_EQUAL(&csid->client_addr, &sid->client_addr)) ||
8882ec7cc7fSKrishna Yenduri 	    bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) {
8892ec7cc7fSKrishna Yenduri 		mutex_exit(lock);
8902ec7cc7fSKrishna Yenduri 		return;
8912ec7cc7fSKrishna Yenduri 	}
8922ec7cc7fSKrishna Yenduri 	csid->cached = B_FALSE;
8932ec7cc7fSKrishna Yenduri 	mutex_exit(lock);
8942ec7cc7fSKrishna Yenduri 
8952ec7cc7fSKrishna Yenduri 	KSSL_COUNTER(sid_uncached, 1);
8962ec7cc7fSKrishna Yenduri }
8972ec7cc7fSKrishna Yenduri 
8982ec7cc7fSKrishna Yenduri static void
8992ec7cc7fSKrishna Yenduri kssl_lookup_sid(sslSessionID *sid, uchar_t *s, in6_addr_t *faddr,
9002ec7cc7fSKrishna Yenduri     kssl_entry_t *kssl_entry)
9012ec7cc7fSKrishna Yenduri {
9022ec7cc7fSKrishna Yenduri 	uint_t index;
9032ec7cc7fSKrishna Yenduri 	kmutex_t *lock;
9042ec7cc7fSKrishna Yenduri 	sslSessionID *csid;
9052ec7cc7fSKrishna Yenduri 
9062ec7cc7fSKrishna Yenduri 	KSSL_COUNTER(sid_cache_lookups, 1);
9072ec7cc7fSKrishna Yenduri 
9082ec7cc7fSKrishna Yenduri 	SET_HASH_INDEX(index, s, faddr);
9092ec7cc7fSKrishna Yenduri 	index %= kssl_entry->sid_cache_nentries;
9102ec7cc7fSKrishna Yenduri 
9112ec7cc7fSKrishna Yenduri 	lock = &(kssl_entry->sid_cache[index].se_lock);
9122ec7cc7fSKrishna Yenduri 	mutex_enter(lock);
9132ec7cc7fSKrishna Yenduri 	csid = &(kssl_entry->sid_cache[index].se_sid);
9142ec7cc7fSKrishna Yenduri 	if (csid->cached == B_FALSE ||
9152ec7cc7fSKrishna Yenduri 	    !IN6_ARE_ADDR_EQUAL(&csid->client_addr, faddr) ||
916c28749e9Skais 	    bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) {
917c28749e9Skais 		mutex_exit(lock);
918c28749e9Skais 		return;
919c28749e9Skais 	}
920c28749e9Skais 
921d3d50737SRafael Vanoni 	if (TICK_TO_SEC(ddi_get_lbolt() - csid->time) >
922d3d50737SRafael Vanoni 	    kssl_entry->sid_cache_timeout) {
923c28749e9Skais 		csid->cached = B_FALSE;
924c28749e9Skais 		mutex_exit(lock);
925c28749e9Skais 		return;
926c28749e9Skais 	}
927c28749e9Skais 
928c28749e9Skais 	bcopy(csid, sid, sizeof (*sid));
929c28749e9Skais 	mutex_exit(lock);
930c28749e9Skais 	ASSERT(sid->cached == B_TRUE);
931c28749e9Skais 
932c28749e9Skais 	KSSL_COUNTER(sid_cache_hits, 1);
933c28749e9Skais }
934c28749e9Skais 
935c28749e9Skais static uchar_t *
936c28749e9Skais kssl_rsa_unwrap(uchar_t *buf, size_t *lenp)
937c28749e9Skais {
938c28749e9Skais 	size_t len = *lenp;
939c28749e9Skais 	int i = 2;
940c28749e9Skais 
941c28749e9Skais 	if (buf[0] != 0 || buf[1] != 2) {
942c28749e9Skais 		return (NULL);
943c28749e9Skais 	}
944c28749e9Skais 
945c28749e9Skais 	while (i < len) {
946c28749e9Skais 		if (buf[i++] == 0) {
947c28749e9Skais 			*lenp = len - i;
948c28749e9Skais 			break;
949c28749e9Skais 		}
950c28749e9Skais 	}
951c28749e9Skais 
952c28749e9Skais 	if (i == len) {
953c28749e9Skais 		return (NULL);
954c28749e9Skais 	}
955c28749e9Skais 
956c28749e9Skais 	return (buf + i);
957c28749e9Skais }
958c28749e9Skais 
959c28749e9Skais 
960c28749e9Skais #define	KSSL_SSL3_SH_RECLEN	(74)
961c28749e9Skais #define	KSSL_SSL3_FIN_MSGLEN	(36)
96211d0a659SVladimir Kotal #define	KSSL_EMPTY_RENEG_INFO_LEN	(7)
963c28749e9Skais 
964c28749e9Skais #define	KSSL_SSL3_MAX_CCP_FIN_MSGLEN	(128)	/* comfortable upper bound */
965c28749e9Skais 
96611d0a659SVladimir Kotal /*
96711d0a659SVladimir Kotal  * Send ServerHello record to the client.
96811d0a659SVladimir Kotal  */
969c28749e9Skais static int
970c28749e9Skais kssl_send_server_hello(ssl_t *ssl)
971c28749e9Skais {
972c28749e9Skais 	mblk_t *mp;
973c28749e9Skais 	uchar_t *buf;
974c28749e9Skais 	uchar_t *msgstart;
97511d0a659SVladimir Kotal 	uint16_t reclen = KSSL_SSL3_SH_RECLEN;
976c28749e9Skais 
977c28749e9Skais 	mp = allocb(ssl->tcp_mss, BPRI_HI);
978c28749e9Skais 	if (mp == NULL) {
979c28749e9Skais 		KSSL_COUNTER(alloc_fails, 1);
980c28749e9Skais 		return (ENOMEM);
981c28749e9Skais 	}
982c28749e9Skais 	ssl->handshake_sendbuf = mp;
983c28749e9Skais 	buf = mp->b_wptr;
984c28749e9Skais 
98511d0a659SVladimir Kotal 	if (ssl->secure_renegotiation)
98611d0a659SVladimir Kotal 		reclen += KSSL_EMPTY_RENEG_INFO_LEN;
98711d0a659SVladimir Kotal 
988c28749e9Skais 	/* 5 byte record header */
989c28749e9Skais 	buf[0] = content_handshake;
990c28749e9Skais 	buf[1] = ssl->major_version;
991c28749e9Skais 	buf[2] = ssl->minor_version;
99211d0a659SVladimir Kotal 	buf[3] = reclen >> 8;
99311d0a659SVladimir Kotal 	buf[4] = reclen & 0xff;
994c28749e9Skais 	buf += SSL3_HDR_LEN;
995c28749e9Skais 
996c28749e9Skais 	msgstart = buf;
997c28749e9Skais 
998c28749e9Skais 	/* 6 byte message header */
999c28749e9Skais 	buf[0] = (uchar_t)server_hello;			/* message type */
1000c28749e9Skais 	buf[1] = 0;					/* message len byte 0 */
100111d0a659SVladimir Kotal 	buf[2] = ((reclen - 4) >> 8) &
1002c28749e9Skais 	    0xff;					/* message len byte 1 */
100311d0a659SVladimir Kotal 	buf[3] = (reclen - 4) & 0xff;	/* message len byte 2 */
1004c28749e9Skais 
1005c28749e9Skais 	buf[4] = ssl->major_version;	/* version byte 0 */
1006c28749e9Skais 	buf[5] = ssl->minor_version;	/* version byte 1 */
1007c28749e9Skais 
1008c28749e9Skais 	buf += 6;
1009c28749e9Skais 
1010c28749e9Skais 	kssl_get_hello_random(ssl->server_random);
1011c28749e9Skais 	bcopy(ssl->server_random, buf, SSL3_RANDOM_LENGTH);
1012c28749e9Skais 	buf += SSL3_RANDOM_LENGTH;
1013c28749e9Skais 
1014c28749e9Skais 	buf[0] = SSL3_SESSIONID_BYTES;
1015c28749e9Skais 	bcopy(ssl->sid.session_id, buf + 1, SSL3_SESSIONID_BYTES);
1016c28749e9Skais 	buf += SSL3_SESSIONID_BYTES + 1;
1017c28749e9Skais 
1018c28749e9Skais 	buf[0] = (ssl->pending_cipher_suite >> 8) & 0xff;
1019c28749e9Skais 	buf[1] = ssl->pending_cipher_suite & 0xff;
1020c28749e9Skais 
1021c28749e9Skais 	buf[2] = 0;	/* No compression */
102211d0a659SVladimir Kotal 	buf += 3;
1023c28749e9Skais 
102411d0a659SVladimir Kotal 	/*
102511d0a659SVladimir Kotal 	 * Add "renegotiation_info" extension if the ClientHello message
102611d0a659SVladimir Kotal 	 * contained either SCSV value in cipher suite list or
102711d0a659SVladimir Kotal 	 * "renegotiation_info" extension. This is per RFC 5746, section 3.6.
102811d0a659SVladimir Kotal 	 */
102911d0a659SVladimir Kotal 	if (ssl->secure_renegotiation) {
103011d0a659SVladimir Kotal 		/* Extensions length */
103111d0a659SVladimir Kotal 		buf[0] = 0x00;
103211d0a659SVladimir Kotal 		buf[1] = 0x05;
103311d0a659SVladimir Kotal 		/* empty renegotiation_info extension encoding (section 3.2) */
103411d0a659SVladimir Kotal 		buf[2] = 0xff;
103511d0a659SVladimir Kotal 		buf[3] = 0x01;
103611d0a659SVladimir Kotal 		buf[4] = 0x00;
103711d0a659SVladimir Kotal 		buf[5] = 0x01;
103811d0a659SVladimir Kotal 		buf[6] = 0x00;
103911d0a659SVladimir Kotal 		buf += KSSL_EMPTY_RENEG_INFO_LEN;
104011d0a659SVladimir Kotal 	}
104111d0a659SVladimir Kotal 
104211d0a659SVladimir Kotal 	mp->b_wptr = buf;
1043c28749e9Skais 	ASSERT(mp->b_wptr < mp->b_datap->db_lim);
1044c28749e9Skais 
104511d0a659SVladimir Kotal 	kssl_update_handshake_hashes(ssl, msgstart, reclen);
1046c28749e9Skais 	return (0);
1047c28749e9Skais }
1048c28749e9Skais 
1049c28749e9Skais static void
1050c28749e9Skais kssl_get_hello_random(uchar_t *buf)
1051c28749e9Skais {
1052c28749e9Skais 	timestruc_t ts;
1053c28749e9Skais 	time_t sec;
1054c28749e9Skais 
1055c28749e9Skais 	gethrestime(&ts);
1056c28749e9Skais 	sec = ts.tv_sec;
1057c28749e9Skais 
1058c28749e9Skais 	buf[0] = (sec >> 24) & 0xff;
1059c28749e9Skais 	buf[1] = (sec >> 16) & 0xff;
1060c28749e9Skais 	buf[2] = (sec >> 8) & 0xff;
1061c28749e9Skais 	buf[3] = (sec) & 0xff;
1062c28749e9Skais 
1063c28749e9Skais 	(void) random_get_pseudo_bytes(&buf[4], SSL3_RANDOM_LENGTH - 4);
1064c28749e9Skais 
1065c28749e9Skais 	/* Should this be caching? */
1066c28749e9Skais }
1067c28749e9Skais 
1068c28749e9Skais static int
1069c28749e9Skais kssl_tls_P_hash(crypto_mechanism_t *mech, crypto_key_t *key,
1070c28749e9Skais 	size_t hashlen,
1071c28749e9Skais 	uchar_t *label, size_t label_len,
1072c28749e9Skais 	uchar_t *seed, size_t seedlen,
1073c28749e9Skais 	uchar_t *data, size_t datalen)
1074c28749e9Skais {
1075c28749e9Skais 	int rv = 0;
1076c28749e9Skais 	uchar_t A1[MAX_HASH_LEN], result[MAX_HASH_LEN];
1077dd49f125SAnders Persson 	int bytes_left = (int)datalen;
1078c28749e9Skais 	crypto_data_t dd, mac;
1079c28749e9Skais 	crypto_context_t ctx;
1080c28749e9Skais 
1081c28749e9Skais 	dd.cd_format = CRYPTO_DATA_RAW;
1082c28749e9Skais 	dd.cd_offset = 0;
1083c28749e9Skais 	mac.cd_format = CRYPTO_DATA_RAW;
1084c28749e9Skais 	mac.cd_offset = 0;
1085c28749e9Skais 
1086c28749e9Skais 	/*
10872ec7cc7fSKrishna Yenduri 	 * A(i) = HMAC_hash(secret, seed + A(i-1));
1088c28749e9Skais 	 * A(0) = seed;
1089c28749e9Skais 	 *
1090c28749e9Skais 	 * Compute A(1):
1091c28749e9Skais 	 * A(1) = HMAC_hash(secret, label + seed)
1092c28749e9Skais 	 *
1093c28749e9Skais 	 */
1094c28749e9Skais 	HMAC_INIT(mech, key, &ctx);
1095c28749e9Skais 	HMAC_UPDATE(ctx, label, label_len);
1096c28749e9Skais 	HMAC_UPDATE(ctx, seed, seedlen);
1097c28749e9Skais 	HMAC_FINAL(ctx, A1, hashlen);
1098c28749e9Skais 
1099c28749e9Skais 	/* Compute A(2) ... A(n) */
1100c28749e9Skais 	while (bytes_left > 0) {
1101c28749e9Skais 		HMAC_INIT(mech, key, &ctx);
1102c28749e9Skais 		HMAC_UPDATE(ctx, A1, hashlen);
1103c28749e9Skais 		HMAC_UPDATE(ctx, label, label_len);
1104c28749e9Skais 		HMAC_UPDATE(ctx, seed, seedlen);
1105c28749e9Skais 		HMAC_FINAL(ctx, result, hashlen);
1106c28749e9Skais 
1107c28749e9Skais 		/*
1108c28749e9Skais 		 * The A(i) value is stored in "result".
1109c28749e9Skais 		 * Save the results of the MAC so it can be input to next
1110c28749e9Skais 		 * iteration.
1111c28749e9Skais 		 */
1112c28749e9Skais 		if (bytes_left > hashlen) {
1113c28749e9Skais 			/* Store the chunk result */
1114c28749e9Skais 			bcopy(result, data, hashlen);
1115c28749e9Skais 			data += hashlen;
1116c28749e9Skais 
1117c28749e9Skais 			bytes_left -= hashlen;
1118c28749e9Skais 
1119c28749e9Skais 			/* Update A1 for next iteration */
1120c28749e9Skais 			HMAC_INIT(mech, key, &ctx);
1121c28749e9Skais 			HMAC_UPDATE(ctx, A1, hashlen);
1122c28749e9Skais 			HMAC_FINAL(ctx, A1, hashlen);
1123c28749e9Skais 
1124c28749e9Skais 		} else {
1125c28749e9Skais 			bcopy(result, data, bytes_left);
1126c28749e9Skais 			data += bytes_left;
1127c28749e9Skais 			bytes_left = 0;
1128c28749e9Skais 		}
1129c28749e9Skais 	}
1130c28749e9Skais end:
1131c28749e9Skais 	if (CRYPTO_ERR(rv)) {
113251dd2c77Svk199839 		DTRACE_PROBE1(kssl_err__crypto_mac_error, int, rv);
1133c28749e9Skais 		KSSL_COUNTER(compute_mac_failure, 1);
1134c28749e9Skais 	}
1135c28749e9Skais 	return (rv);
1136c28749e9Skais }
1137c28749e9Skais 
1138c28749e9Skais /* ARGSUSED */
1139c28749e9Skais static int
1140c28749e9Skais kssl_tls_PRF(ssl_t *ssl,
1141c28749e9Skais 	uchar_t *secret, size_t secret_len,
1142c28749e9Skais 	uchar_t *label, size_t label_len,
1143c28749e9Skais 	uchar_t *seed, size_t seed_len,
1144c28749e9Skais 	uchar_t *prfresult, size_t prfresult_len)
1145c28749e9Skais {
1146c28749e9Skais 	/*
1147c28749e9Skais 	 * RFC 2246:
1148c28749e9Skais 	 *  PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
1149c28749e9Skais 	 *				P_SHA1(S2, label + seed);
1150c28749e9Skais 	 * S1 = 1st half of secret.
1151c28749e9Skais 	 * S1 = 2nd half of secret.
1152c28749e9Skais 	 *
1153c28749e9Skais 	 */
1154c28749e9Skais 
11552ec7cc7fSKrishna Yenduri 	int rv, i;
11562bd70d4bSkrishna 	uchar_t psha1[MAX_KEYBLOCK_LENGTH];
1157c28749e9Skais 	crypto_key_t S1, S2;
1158c28749e9Skais 
1159c28749e9Skais 	/* length of secret keys is ceil(length/2) */
1160c28749e9Skais 	size_t slen = roundup(secret_len, 2) / 2;
1161c28749e9Skais 
11622bd70d4bSkrishna 	if (prfresult_len >  MAX_KEYBLOCK_LENGTH) {
116351dd2c77Svk199839 		DTRACE_PROBE1(kssl_err__unexpected_keyblock_size,
116451dd2c77Svk199839 		    size_t, prfresult_len);
1165c28749e9Skais 		return (CRYPTO_ARGUMENTS_BAD);
1166c28749e9Skais 	}
1167c28749e9Skais 
1168c28749e9Skais 	ASSERT(prfresult != NULL);
1169c28749e9Skais 	ASSERT(label != NULL);
1170c28749e9Skais 	ASSERT(seed != NULL);
1171c28749e9Skais 
1172c28749e9Skais 	S1.ck_data   = secret;
1173c28749e9Skais 	S1.ck_length = slen * 8; /* bits */
1174c28749e9Skais 	S1.ck_format = CRYPTO_KEY_RAW;
1175c28749e9Skais 
1176c28749e9Skais 	S2.ck_data   = secret + slen;
1177c28749e9Skais 	S2.ck_length = slen * 8; /* bits */
1178c28749e9Skais 	S2.ck_format = CRYPTO_KEY_RAW;
1179c28749e9Skais 
1180c28749e9Skais 	rv = kssl_tls_P_hash(&hmac_md5_mech, &S1, MD5_HASH_LEN,
1181c28749e9Skais 	    label, label_len,
1182c28749e9Skais 	    seed, seed_len,
1183c28749e9Skais 	    prfresult, prfresult_len);
1184c28749e9Skais 	if (CRYPTO_ERR(rv))
1185c28749e9Skais 		goto end;
1186c28749e9Skais 
1187c28749e9Skais 	rv = kssl_tls_P_hash(&hmac_sha1_mech, &S2, SHA1_HASH_LEN,
1188c28749e9Skais 	    label, label_len,
1189c28749e9Skais 	    seed, seed_len,
1190c28749e9Skais 	    psha1, prfresult_len);
1191c28749e9Skais 	if (CRYPTO_ERR(rv))
1192c28749e9Skais 		goto end;
1193c28749e9Skais 
1194c28749e9Skais 	for (i = 0; i < prfresult_len; i++)
1195c28749e9Skais 		prfresult[i] ^= psha1[i];
1196c28749e9Skais 
1197c28749e9Skais end:
1198c28749e9Skais 	if (CRYPTO_ERR(rv))
1199c28749e9Skais 		bzero(prfresult, prfresult_len);
1200c28749e9Skais 
1201c28749e9Skais 	return (rv);
1202c28749e9Skais }
1203c28749e9Skais 
1204968d6ddeSkrishna #define	IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)			\
1205968d6ddeSkrishna 	(pms == NULL || pmslen != SSL3_PRE_MASTER_SECRET_LEN ||		\
1206968d6ddeSkrishna 	pms[0] != ssl->major_version || pms[1] != ssl->minor_version)
1207968d6ddeSkrishna 
1208968d6ddeSkrishna #define	FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf) {			\
1209968d6ddeSkrishna 		KSSL_COUNTER(bad_pre_master_secret, 1);			\
1210968d6ddeSkrishna 		pms = buf;						\
1211968d6ddeSkrishna 		pmslen = SSL3_PRE_MASTER_SECRET_LEN;			\
1212968d6ddeSkrishna 		pms[0] = ssl->major_version;				\
1213968d6ddeSkrishna 		pms[1] = ssl->minor_version;				\
1214968d6ddeSkrishna 		(void) random_get_pseudo_bytes(&buf[2], pmslen - 2);	\
1215968d6ddeSkrishna }
1216968d6ddeSkrishna 
1217c28749e9Skais static int
1218c28749e9Skais kssl_generate_tls_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen)
1219c28749e9Skais {
1220968d6ddeSkrishna 	uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN];
1221c28749e9Skais 	uchar_t seed[SSL3_RANDOM_LENGTH * 2];
1222c28749e9Skais 
1223c28749e9Skais 	/*
1224c28749e9Skais 	 * Computing the master secret:
1225c28749e9Skais 	 * ----------------------------
1226c28749e9Skais 	 * master_secret = PRF (pms, "master secret",
1227c28749e9Skais 	 *		ClientHello.random + ServerHello.random);
1228c28749e9Skais 	 */
1229c28749e9Skais 	bcopy(ssl->client_random, seed, SSL3_RANDOM_LENGTH);
1230c28749e9Skais 	bcopy(ssl->server_random, seed + SSL3_RANDOM_LENGTH,
1231c28749e9Skais 	    SSL3_RANDOM_LENGTH);
1232c28749e9Skais 
1233968d6ddeSkrishna 	/* if pms is bad fake it to thwart Bleichenbacher attack */
1234968d6ddeSkrishna 	if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) {
123551dd2c77Svk199839 		DTRACE_PROBE(kssl_err__under_Bleichenbacher_attack);
1236968d6ddeSkrishna 		FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf);
1237968d6ddeSkrishna 	}
1238968d6ddeSkrishna 
1239c28749e9Skais 	return (kssl_tls_PRF(ssl,
1240c28749e9Skais 	    pms, pmslen,
1241c28749e9Skais 	    (uchar_t *)TLS_MASTER_SECRET_LABEL,
1242c28749e9Skais 	    (size_t)strlen(TLS_MASTER_SECRET_LABEL),
1243c28749e9Skais 	    seed, sizeof (seed),
1244c28749e9Skais 	    ssl->sid.master_secret,
1245c28749e9Skais 	    (size_t)sizeof (ssl->sid.master_secret)));
1246c28749e9Skais }
1247c28749e9Skais 
1248968d6ddeSkrishna 
1249c28749e9Skais static void
1250c28749e9Skais kssl_generate_ssl_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen)
1251c28749e9Skais {
1252c28749e9Skais 	uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN];
1253c28749e9Skais 	uchar_t *ms;
1254c28749e9Skais 	int hlen = MD5_HASH_LEN;
1255c28749e9Skais 
1256c28749e9Skais 	ms = ssl->sid.master_secret;
1257c28749e9Skais 
1258c28749e9Skais 	/* if pms is bad fake it to thwart Bleichenbacher attack */
1259968d6ddeSkrishna 	if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) {
126051dd2c77Svk199839 		DTRACE_PROBE(kssl_err__under_Bleichenbacher_attack);
1261968d6ddeSkrishna 		FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf);
1262c28749e9Skais 	}
1263968d6ddeSkrishna 
1264c28749e9Skais 	kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 1, ms, 0);
1265c28749e9Skais 	kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 2, ms + hlen, 0);
1266c28749e9Skais 	kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 3, ms + 2 * hlen,
1267c28749e9Skais 	    0);
1268c28749e9Skais }
1269c28749e9Skais 
1270c28749e9Skais static int
1271c28749e9Skais kssl_generate_tls_keyblock(ssl_t *ssl)
1272c28749e9Skais {
1273c28749e9Skais 	uchar_t seed[2 * SSL3_RANDOM_LENGTH];
1274c28749e9Skais 
1275c28749e9Skais 	bcopy(ssl->server_random, seed, SSL3_RANDOM_LENGTH);
1276c28749e9Skais 	bcopy(ssl->client_random, seed + SSL3_RANDOM_LENGTH,
1277c28749e9Skais 	    SSL3_RANDOM_LENGTH);
1278c28749e9Skais 
1279c28749e9Skais 	return (kssl_tls_PRF(ssl, ssl->sid.master_secret,
1280c28749e9Skais 	    (size_t)SSL3_MASTER_SECRET_LEN,
1281c28749e9Skais 	    (uchar_t *)TLS_KEY_EXPANSION_LABEL,
1282c28749e9Skais 	    (size_t)strlen(TLS_KEY_EXPANSION_LABEL),
1283c28749e9Skais 	    seed, (size_t)sizeof (seed),
1284c28749e9Skais 	    ssl->pending_keyblock,
1285c28749e9Skais 	    (size_t)ssl->pending_keyblksz));
1286c28749e9Skais 
1287c28749e9Skais }
1288c28749e9Skais 
1289c28749e9Skais static void
1290c28749e9Skais kssl_generate_keyblock(ssl_t *ssl)
1291c28749e9Skais {
1292c28749e9Skais 	uchar_t *ms;
1293c28749e9Skais 	size_t mslen = SSL3_MASTER_SECRET_LEN;
1294c28749e9Skais 	int hlen = MD5_HASH_LEN;
1295c28749e9Skais 	uchar_t *keys = ssl->pending_keyblock;
1296c28749e9Skais 	int steps = howmany(ssl->pending_keyblksz, hlen);
1297c28749e9Skais 	int i;
1298c28749e9Skais 
1299c28749e9Skais 	ms = ssl->sid.master_secret;
1300c28749e9Skais 
1301c28749e9Skais 	ASSERT(hlen * steps <= MAX_KEYBLOCK_LENGTH);
1302c28749e9Skais 
1303c28749e9Skais 	for (i = 1; i <= steps; i++) {
1304c28749e9Skais 		kssl_ssl3_key_material_derive_step(ssl, ms, mslen, i, keys, 1);
1305c28749e9Skais 		keys += hlen;
1306c28749e9Skais 	}
1307c28749e9Skais }
1308c28749e9Skais 
13092bd70d4bSkrishna static char *ssl3_key_derive_seeds[9] = {"A", "BB", "CCC", "DDDD", "EEEEE",
13102bd70d4bSkrishna 	"FFFFFF", "GGGGGGG", "HHHHHHHH", "IIIIIIIII"};
1311c28749e9Skais 
1312c28749e9Skais static void
1313c28749e9Skais kssl_ssl3_key_material_derive_step(
1314c28749e9Skais 	ssl_t *ssl,
1315c28749e9Skais 	uchar_t *secret,
1316c28749e9Skais 	size_t secretlen,
1317c28749e9Skais 	int step,
1318c28749e9Skais 	uchar_t *dst,
1319c28749e9Skais 	int sr_first)
1320c28749e9Skais {
1321c28749e9Skais 	SHA1_CTX sha1, *sha1ctx;
1322c28749e9Skais 	MD5_CTX md5, *md5ctx;
1323c28749e9Skais 	uchar_t sha1_hash[SHA1_HASH_LEN];
1324c28749e9Skais 
1325c28749e9Skais 	sha1ctx = &sha1;
1326c28749e9Skais 	md5ctx = &md5;
1327c28749e9Skais 
1328c28749e9Skais 	ASSERT(step <=
1329c28749e9Skais 	    sizeof (ssl3_key_derive_seeds) /
1330c28749e9Skais 	    sizeof (ssl3_key_derive_seeds[0]));
1331c28749e9Skais 	step--;
1332c28749e9Skais 
1333c28749e9Skais 	SHA1Init(sha1ctx);
1334c28749e9Skais 	SHA1Update(sha1ctx, (uchar_t *)ssl3_key_derive_seeds[step],
1335c28749e9Skais 	    step + 1);
1336c28749e9Skais 	SHA1Update(sha1ctx, secret, secretlen);
1337c28749e9Skais 	if (sr_first) {
1338c28749e9Skais 		SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH);
1339c28749e9Skais 		SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH);
1340c28749e9Skais 	} else {
1341c28749e9Skais 		SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH);
1342c28749e9Skais 		SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH);
1343c28749e9Skais 	}
1344c28749e9Skais 	SHA1Final(sha1_hash, sha1ctx);
1345c28749e9Skais 
1346c28749e9Skais 	MD5Init(md5ctx);
1347c28749e9Skais 	MD5Update(md5ctx, secret, secretlen);
1348c28749e9Skais 	MD5Update(md5ctx, sha1_hash, SHA1_HASH_LEN);
1349c28749e9Skais 	MD5Final(dst, md5ctx);
1350c28749e9Skais }
1351c28749e9Skais 
1352c28749e9Skais static int
1353c28749e9Skais kssl_send_certificate_and_server_hello_done(ssl_t *ssl)
1354c28749e9Skais {
1355c28749e9Skais 	int cur_reclen;
1356c28749e9Skais 	int mss;
1357c28749e9Skais 	int len, copylen;
1358c28749e9Skais 	mblk_t *mp;
1359c28749e9Skais 	uchar_t *cert_buf;
1360c28749e9Skais 	int cert_len;
1361c28749e9Skais 	uchar_t *msgbuf;
1362c28749e9Skais 	Certificate_t *cert;
136311d0a659SVladimir Kotal 	uint16_t reclen = KSSL_SSL3_SH_RECLEN;
1364c28749e9Skais 
1365c28749e9Skais 	cert = ssl->kssl_entry->ke_server_certificate;
1366c28749e9Skais 	if (cert == NULL) {
1367c28749e9Skais 		return (ENOENT);
1368c28749e9Skais 	}
1369c28749e9Skais 	cert_buf = cert->msg;
1370c28749e9Skais 	cert_len = cert->len;
1371c28749e9Skais 
137211d0a659SVladimir Kotal 	if (ssl->secure_renegotiation)
137311d0a659SVladimir Kotal 		reclen += KSSL_EMPTY_RENEG_INFO_LEN;
137411d0a659SVladimir Kotal 
1375c28749e9Skais 	mp = ssl->handshake_sendbuf;
1376c28749e9Skais 	mss = ssl->tcp_mss;
1377c28749e9Skais 	ASSERT(mp != NULL);
1378c28749e9Skais 	cur_reclen = mp->b_wptr - mp->b_rptr - SSL3_HDR_LEN;
137911d0a659SVladimir Kotal 	ASSERT(cur_reclen == reclen);
1380c28749e9Skais 	/* Assume MSS is at least 80 bytes */
1381c28749e9Skais 	ASSERT(mss > cur_reclen + SSL3_HDR_LEN);
1382c28749e9Skais 	ASSERT(cur_reclen < SSL3_MAX_RECORD_LENGTH); /* XXX */
1383c28749e9Skais 
1384c28749e9Skais 	copylen = mss - (cur_reclen + SSL3_HDR_LEN);
1385c28749e9Skais 	len = cert_len;
1386c28749e9Skais 	copylen = MIN(copylen, len);
1387c28749e9Skais 	copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen);
1388c28749e9Skais 
1389c28749e9Skais 	/* new record always starts in a new mblk for simplicity */
1390c28749e9Skais 	msgbuf = cert_buf;
1391c28749e9Skais 	for (;;) {
1392c28749e9Skais 		ASSERT(mp->b_wptr + copylen <= mp->b_datap->db_lim);
1393c28749e9Skais 		bcopy(msgbuf, mp->b_wptr, copylen);
1394c28749e9Skais 		msgbuf += copylen;
1395c28749e9Skais 		mp->b_wptr += copylen;
1396c28749e9Skais 		cur_reclen += copylen;
1397c28749e9Skais 		len -= copylen;
1398c28749e9Skais 		if (len == 0) {
1399c28749e9Skais 			break;
1400c28749e9Skais 		}
1401c28749e9Skais 		if (cur_reclen == SSL3_MAX_RECORD_LENGTH) {
1402c28749e9Skais 			cur_reclen = 0;
1403c28749e9Skais 		}
1404c28749e9Skais 		copylen = MIN(len, mss);
1405c28749e9Skais 		copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen);
1406c28749e9Skais 		mp->b_cont = allocb(copylen, BPRI_HI);
1407c28749e9Skais 		if (mp->b_cont == NULL) {
1408c28749e9Skais 			KSSL_COUNTER(alloc_fails, 1);
1409c28749e9Skais 			freemsg(ssl->handshake_sendbuf);
1410c28749e9Skais 			ssl->handshake_sendbuf = NULL;
1411c28749e9Skais 			return (ENOMEM);
1412c28749e9Skais 		}
1413c28749e9Skais 		mp = mp->b_cont;
1414c28749e9Skais 		if (cur_reclen == 0) {
1415c28749e9Skais 			mp->b_wptr[0] = content_handshake;
1416c28749e9Skais 			mp->b_wptr[1] = ssl->major_version;
1417c28749e9Skais 			mp->b_wptr[2] = ssl->minor_version;
141811d0a659SVladimir Kotal 			cur_reclen = MIN(len, reclen);
1419c28749e9Skais 			mp->b_wptr[3] = (cur_reclen >> 8) & 0xff;
1420c28749e9Skais 			mp->b_wptr[4] = (cur_reclen) & 0xff;
1421c28749e9Skais 			mp->b_wptr += SSL3_HDR_LEN;
1422c28749e9Skais 			cur_reclen = 0;
1423c28749e9Skais 			copylen = MIN(copylen, mss - SSL3_HDR_LEN);
1424c28749e9Skais 		}
1425c28749e9Skais 	}
1426c28749e9Skais 
1427c28749e9Skais 	/* adjust the record length field for the first record */
1428c28749e9Skais 	mp = ssl->handshake_sendbuf;
142911d0a659SVladimir Kotal 	cur_reclen = MIN(reclen + cert_len, SSL3_MAX_RECORD_LENGTH);
1430c28749e9Skais 	mp->b_rptr[3] = (cur_reclen >> 8) & 0xff;
1431c28749e9Skais 	mp->b_rptr[4] = (cur_reclen) & 0xff;
1432c28749e9Skais 
1433c28749e9Skais 	kssl_update_handshake_hashes(ssl, cert_buf, cert_len);
1434c28749e9Skais 
1435c28749e9Skais 	return (0);
1436c28749e9Skais }
1437c28749e9Skais 
1438c28749e9Skais static int
1439c28749e9Skais kssl_send_change_cipher_specs(ssl_t *ssl)
1440c28749e9Skais {
1441c28749e9Skais 	mblk_t *mp, *newmp;
1442c28749e9Skais 	uchar_t *buf;
1443c28749e9Skais 
1444c28749e9Skais 	mp = ssl->handshake_sendbuf;
1445c28749e9Skais 
1446c28749e9Skais 	/* We're most likely to hit the fast path for resumed sessions */
1447c28749e9Skais 	if ((mp != NULL) &&
1448c28749e9Skais 	    (mp->b_datap->db_lim - mp->b_wptr > KSSL_SSL3_MAX_CCP_FIN_MSGLEN)) {
1449c28749e9Skais 		buf = mp->b_wptr;
1450c28749e9Skais 	} else {
1451c28749e9Skais 		newmp = allocb(KSSL_SSL3_MAX_CCP_FIN_MSGLEN, BPRI_HI);
1452c28749e9Skais 
1453c28749e9Skais 		if (newmp == NULL)
1454c28749e9Skais 			return (ENOMEM);	/* need to do better job! */
1455c28749e9Skais 
1456c28749e9Skais 		if (mp == NULL) {
1457c28749e9Skais 			ssl->handshake_sendbuf = newmp;
1458c28749e9Skais 		} else {
1459c28749e9Skais 			linkb(ssl->handshake_sendbuf, newmp);
1460c28749e9Skais 		}
1461c28749e9Skais 		mp = newmp;
1462c28749e9Skais 		buf = mp->b_rptr;
1463c28749e9Skais 	}
1464c28749e9Skais 
1465c28749e9Skais 	/* 5 byte record header */
1466c28749e9Skais 	buf[0] = content_change_cipher_spec;
1467c28749e9Skais 	buf[1] = ssl->major_version;
1468c28749e9Skais 	buf[2] = ssl->minor_version;
1469c28749e9Skais 	buf[3] = 0;
1470c28749e9Skais 	buf[4] = 1;
1471c28749e9Skais 	buf += SSL3_HDR_LEN;
1472c28749e9Skais 
1473c28749e9Skais 	buf[0] = 1;
1474c28749e9Skais 
1475c28749e9Skais 	mp->b_wptr = buf + 1;
1476c28749e9Skais 	ASSERT(mp->b_wptr < mp->b_datap->db_lim);
1477c28749e9Skais 
1478c28749e9Skais 	ssl->seq_num[KSSL_WRITE] = 0;
1479c28749e9Skais 	return (kssl_spec_init(ssl, KSSL_WRITE));
1480c28749e9Skais }
1481c28749e9Skais 
1482c28749e9Skais int
1483c28749e9Skais kssl_spec_init(ssl_t *ssl, int dir)
1484c28749e9Skais {
1485c28749e9Skais 	KSSL_HASHCTX *ctx;
1486c28749e9Skais 	KSSLCipherSpec *spec = &ssl->spec[dir];
1487c28749e9Skais 	int ret = 0;
1488c28749e9Skais 
1489c28749e9Skais 	spec->mac_hashsz = mac_defs[ssl->pending_malg].hashsz;
1490c28749e9Skais 	spec->mac_padsz = mac_defs[ssl->pending_malg].padsz;
1491c28749e9Skais 
1492c28749e9Skais 	spec->MAC_HashInit = mac_defs[ssl->pending_malg].HashInit;
1493c28749e9Skais 	spec->MAC_HashUpdate = mac_defs[ssl->pending_malg].HashUpdate;
1494c28749e9Skais 	spec->MAC_HashFinal = mac_defs[ssl->pending_malg].HashFinal;
1495c28749e9Skais 
1496c28749e9Skais 	if (dir == KSSL_READ) {
1497c28749e9Skais 		bcopy(ssl->pending_keyblock, ssl->mac_secret[dir],
1498c28749e9Skais 		    spec->mac_hashsz);
1499c28749e9Skais 	} else {
1500c28749e9Skais 		bcopy(&(ssl->pending_keyblock[spec->mac_hashsz]),
1501c28749e9Skais 		    ssl->mac_secret[dir], spec->mac_hashsz);
1502c28749e9Skais 	}
1503c28749e9Skais 
1504c28749e9Skais 	/* Pre-compute these here. will save cycles on each record later */
1505c28749e9Skais 	if (!IS_TLS(ssl)) {
1506c28749e9Skais 		ctx = &ssl->mac_ctx[dir][0];
1507c28749e9Skais 		spec->MAC_HashInit((void *)ctx);
1508c28749e9Skais 		spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir],
1509c28749e9Skais 		    spec->mac_hashsz);
1510c28749e9Skais 		spec->MAC_HashUpdate((void *)ctx, kssl_pad_1,
1511c28749e9Skais 		    spec->mac_padsz);
1512c28749e9Skais 
1513c28749e9Skais 		ctx = &ssl->mac_ctx[dir][1];
1514c28749e9Skais 		spec->MAC_HashInit((void *)ctx);
1515c28749e9Skais 		spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir],
1516c28749e9Skais 		    spec->mac_hashsz);
1517c28749e9Skais 		spec->MAC_HashUpdate((void *)ctx, kssl_pad_2,
1518c28749e9Skais 		    spec->mac_padsz);
1519c28749e9Skais 	}
1520c28749e9Skais 
1521c28749e9Skais 	spec->cipher_type = cipher_defs[ssl->pending_calg].type;
1522c28749e9Skais 	spec->cipher_mech.cm_type = cipher_defs[ssl->pending_calg].mech_type;
1523c28749e9Skais 	spec->cipher_bsize = cipher_defs[ssl->pending_calg].bsize;
1524c28749e9Skais 	spec->cipher_keysz = cipher_defs[ssl->pending_calg].keysz;
1525c28749e9Skais 
1526c28749e9Skais 	if (spec->cipher_ctx != NULL) {
1527c28749e9Skais 		crypto_cancel_ctx(spec->cipher_ctx);
1528c28749e9Skais 		spec->cipher_ctx = 0;
1529c28749e9Skais 	}
1530c28749e9Skais 
1531c28749e9Skais 	/*
1532efe05f9eSkrishna 	 * Initialize HMAC keys for TLS and SSL3 HMAC keys
1533efe05f9eSkrishna 	 * for SSL 3.0.
1534c28749e9Skais 	 */
1535c28749e9Skais 	if (IS_TLS(ssl)) {
1536c28749e9Skais 		if (ssl->pending_malg == mac_md5) {
1537c28749e9Skais 			spec->hmac_mech = hmac_md5_mech;
1538c28749e9Skais 		} else if (ssl->pending_malg == mac_sha) {
1539c28749e9Skais 			spec->hmac_mech = hmac_sha1_mech;
1540c28749e9Skais 		}
1541c28749e9Skais 
1542c28749e9Skais 		spec->hmac_key.ck_format = CRYPTO_KEY_RAW;
1543c28749e9Skais 		spec->hmac_key.ck_data = ssl->mac_secret[dir];
1544c28749e9Skais 		spec->hmac_key.ck_length = spec->mac_hashsz * 8;
1545efe05f9eSkrishna 	} else {
1546efe05f9eSkrishna 		static uint32_t param;
1547efe05f9eSkrishna 
1548efe05f9eSkrishna 		spec->hmac_mech.cm_type = CRYPTO_MECH_INVALID;
1549efe05f9eSkrishna 		spec->hmac_mech.cm_param = (caddr_t)&param;
1550efe05f9eSkrishna 		spec->hmac_mech.cm_param_len = sizeof (param);
1551efe05f9eSkrishna 		if (ssl->pending_malg == mac_md5) {
1552efe05f9eSkrishna 			spec->hmac_mech.cm_type =
1553efe05f9eSkrishna 			    crypto_mech2id("CKM_SSL3_MD5_MAC");
1554efe05f9eSkrishna 			param = MD5_HASH_LEN;
1555efe05f9eSkrishna 		} else if (ssl->pending_malg == mac_sha) {
1556efe05f9eSkrishna 			spec->hmac_mech.cm_type =
1557efe05f9eSkrishna 			    crypto_mech2id("CKM_SSL3_SHA1_MAC");
1558efe05f9eSkrishna 			param = SHA1_HASH_LEN;
1559efe05f9eSkrishna 		}
1560efe05f9eSkrishna 
1561efe05f9eSkrishna 		spec->hmac_key.ck_format = CRYPTO_KEY_RAW;
1562efe05f9eSkrishna 		spec->hmac_key.ck_data = ssl->mac_secret[dir];
1563efe05f9eSkrishna 		spec->hmac_key.ck_length = spec->mac_hashsz * 8;
1564c28749e9Skais 	}
1565c28749e9Skais 
1566c28749e9Skais 	/* We're done if this is the nil cipher */
1567c28749e9Skais 	if (spec->cipher_keysz == 0) {
1568c28749e9Skais 		return (0);
1569c28749e9Skais 	}
1570c28749e9Skais 
1571c28749e9Skais 	/* Initialize the key and the active context */
1572c28749e9Skais 	spec->cipher_key.ck_format = CRYPTO_KEY_RAW;
1573c28749e9Skais 	spec->cipher_key.ck_length = 8 * spec->cipher_keysz; /* in bits */
1574c28749e9Skais 
1575c28749e9Skais 	if (cipher_defs[ssl->pending_calg].bsize > 0) {
1576c28749e9Skais 		/* client_write_IV */
1577c28749e9Skais 		spec->cipher_mech.cm_param =
1578c28749e9Skais 		    (caddr_t)&(ssl->pending_keyblock[2 * spec->mac_hashsz +
1579c28749e9Skais 		    2 * spec->cipher_keysz]);
1580c28749e9Skais 		spec->cipher_mech.cm_param_len = spec->cipher_bsize;
1581c28749e9Skais 	}
1582c28749e9Skais 	spec->cipher_data.cd_format = CRYPTO_DATA_RAW;
1583c28749e9Skais 	if (dir == KSSL_READ) {
1584c28749e9Skais 		spec->cipher_mech.cm_param_len =
1585c28749e9Skais 		    cipher_defs[ssl->pending_calg].bsize;
1586c28749e9Skais 
1587c892ebf1Skrishna 		/* client_write_key */
1588c28749e9Skais 		spec->cipher_key.ck_data =
1589c28749e9Skais 		    &(ssl->pending_keyblock[2 * spec->mac_hashsz]);
1590c28749e9Skais 
1591c28749e9Skais 		ret = crypto_decrypt_init(&(spec->cipher_mech),
1592c28749e9Skais 		    &(spec->cipher_key), NULL, &spec->cipher_ctx, NULL);
1593c28749e9Skais 		if (CRYPTO_ERR(ret)) {
159451dd2c77Svk199839 			DTRACE_PROBE1(kssl_err__crypto_decrypt_init_read,
159551dd2c77Svk199839 			    int, ret);
1596c28749e9Skais 		}
1597c28749e9Skais 	} else {
1598c28749e9Skais 		if (cipher_defs[ssl->pending_calg].bsize > 0) {
159951144063SKrishna Yenduri 			/* server_write_IV */
1600c28749e9Skais 			spec->cipher_mech.cm_param += spec->cipher_bsize;
1601c28749e9Skais 		}
160251144063SKrishna Yenduri 
1603c28749e9Skais 		/* server_write_key */
1604c28749e9Skais 		spec->cipher_key.ck_data =
1605c28749e9Skais 		    &(ssl->pending_keyblock[2 * spec->mac_hashsz +
1606c28749e9Skais 		    spec->cipher_keysz]);
1607c28749e9Skais 
1608c28749e9Skais 		ret = crypto_encrypt_init(&(spec->cipher_mech),
1609c28749e9Skais 		    &(spec->cipher_key), NULL, &spec->cipher_ctx, NULL);
1610c28749e9Skais 		if (CRYPTO_ERR(ret))
161151dd2c77Svk199839 			DTRACE_PROBE1(kssl_err__crypto_encrypt_init_non_read,
161251dd2c77Svk199839 			    int, ret);
1613c28749e9Skais 	}
1614c28749e9Skais 	return (ret);
1615c28749e9Skais }
1616c28749e9Skais 
1617c28749e9Skais static int
1618c28749e9Skais kssl_send_finished(ssl_t *ssl, int update_hsh)
1619c28749e9Skais {
1620c28749e9Skais 	mblk_t *mp;
1621c28749e9Skais 	uchar_t *buf;
1622c28749e9Skais 	uchar_t *rstart;
1623c28749e9Skais 	uchar_t *versionp;
1624c28749e9Skais 	SSL3Hashes ssl3hashes;
1625dd49f125SAnders Persson 	uchar_t finish_len;
16262ec7cc7fSKrishna Yenduri 	int ret;
162711d0a659SVladimir Kotal 	uint16_t adj_len = 0;
1628c28749e9Skais 
1629c28749e9Skais 	mp = ssl->handshake_sendbuf;
1630c28749e9Skais 	ASSERT(mp != NULL);
1631c28749e9Skais 	buf = mp->b_wptr;
163211d0a659SVladimir Kotal 	if (ssl->secure_renegotiation)
163311d0a659SVladimir Kotal 		adj_len = KSSL_EMPTY_RENEG_INFO_LEN;
163411d0a659SVladimir Kotal 	/*
163511d0a659SVladimir Kotal 	 * It should be either a message with Server Hello record or just plain
163611d0a659SVladimir Kotal 	 * SSL header (data packet).
163711d0a659SVladimir Kotal 	 */
163811d0a659SVladimir Kotal 	ASSERT(buf - mp->b_rptr ==
163911d0a659SVladimir Kotal 	    SSL3_HDR_LEN + KSSL_SSL3_SH_RECLEN + SSL3_HDR_LEN + 1 + adj_len ||
164011d0a659SVladimir Kotal 	    buf - mp->b_rptr == SSL3_HDR_LEN + 1);
1641c28749e9Skais 
1642c28749e9Skais 	rstart = buf;
1643c28749e9Skais 
1644c28749e9Skais 	if (IS_TLS(ssl))
1645c28749e9Skais 		finish_len = TLS_FINISHED_SIZE;
1646c28749e9Skais 	else
1647c28749e9Skais 		finish_len = KSSL_SSL3_FIN_MSGLEN;
1648c28749e9Skais 
1649c28749e9Skais 	/* 5 byte record header */
1650c28749e9Skais 	buf[0] = content_handshake;
1651c28749e9Skais 	buf[1] = ssl->major_version;
1652c28749e9Skais 	buf[2] = ssl->minor_version;
1653c28749e9Skais 	buf[3] = 0;
1654c28749e9Skais 	buf[4] = 4 + finish_len;
1655c28749e9Skais 
1656c28749e9Skais 	versionp = &buf[1];
1657c28749e9Skais 
1658c28749e9Skais 	buf += SSL3_HDR_LEN;
1659c28749e9Skais 
1660c28749e9Skais 	/* 4 byte message header */
1661c28749e9Skais 	buf[0] = (uchar_t)finished;	/* message type */
1662c28749e9Skais 	buf[1] = 0;			/* message len byte 0 */
1663c28749e9Skais 	buf[2] = 0;			/* message len byte 1 */
1664c28749e9Skais 	buf[3] = finish_len;	/* message len byte 2 */
1665c28749e9Skais 	buf += 4;
1666c28749e9Skais 
1667c28749e9Skais 	if (IS_TLS(ssl)) {
1668c28749e9Skais 		bcopy(ssl->hs_hashes.md5, ssl3hashes.md5,
1669c28749e9Skais 		    sizeof (ssl3hashes.md5));
1670c28749e9Skais 		bcopy(ssl->hs_hashes.sha1, ssl3hashes.sha1,
1671c28749e9Skais 		    sizeof (ssl3hashes.sha1));
1672c28749e9Skais 	}
1673c28749e9Skais 
1674c28749e9Skais 	/* Compute hashes for the SENDER side */
1675c28749e9Skais 	ret = kssl_compute_handshake_hashes(ssl, &ssl3hashes, sender_server);
1676c28749e9Skais 	if (ret != 0)
1677c28749e9Skais 		return (ret);
1678c28749e9Skais 
1679c28749e9Skais 	if (IS_TLS(ssl)) {
1680c28749e9Skais 		bcopy(ssl3hashes.tlshash, buf, sizeof (ssl3hashes.tlshash));
1681c28749e9Skais 	} else {
1682c28749e9Skais 		bcopy(ssl3hashes.md5, buf, MD5_HASH_LEN);
1683c28749e9Skais 		bcopy(ssl3hashes.sha1, buf + MD5_HASH_LEN, SHA1_HASH_LEN);
1684c28749e9Skais 	}
1685c28749e9Skais 
1686c28749e9Skais 	if (update_hsh) {
1687c28749e9Skais 		kssl_update_handshake_hashes(ssl, buf - 4, finish_len + 4);
1688c28749e9Skais 	}
1689c28749e9Skais 
1690c28749e9Skais 	mp->b_wptr = buf + finish_len;
1691c28749e9Skais 
1692c28749e9Skais 	ret = kssl_mac_encrypt_record(ssl, content_handshake, versionp,
1693c28749e9Skais 	    rstart, mp);
1694c28749e9Skais 	ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
1695c28749e9Skais 
1696c28749e9Skais 	return (ret);
1697c28749e9Skais }
1698c28749e9Skais 
1699c28749e9Skais int
1700c28749e9Skais kssl_mac_encrypt_record(ssl_t *ssl,
1701c28749e9Skais 	SSL3ContentType ct,
1702c28749e9Skais 	uchar_t *versionp,
1703c28749e9Skais 	uchar_t *rstart,
1704c28749e9Skais 	mblk_t *mp)
1705c28749e9Skais {
1706c28749e9Skais 	KSSLCipherSpec *spec;
1707c28749e9Skais 	int mac_sz;
1708c28749e9Skais 	int ret = 0;
1709c28749e9Skais 	uint16_t rec_sz;
1710c28749e9Skais 	int pad_sz;
1711c28749e9Skais 	int i;
1712c28749e9Skais 
1713c28749e9Skais 	ASSERT(ssl != NULL);
1714c28749e9Skais 	ASSERT(rstart >= mp->b_rptr);
1715c28749e9Skais 	ASSERT(rstart < mp->b_wptr);
1716c28749e9Skais 
1717c28749e9Skais 	spec = &ssl->spec[KSSL_WRITE];
1718c28749e9Skais 	mac_sz = spec->mac_hashsz;
1719c28749e9Skais 
1720c28749e9Skais 	rec_sz = (mp->b_wptr - rstart) - SSL3_HDR_LEN;
1721c28749e9Skais 	ASSERT(rec_sz > 0);
1722c28749e9Skais 
1723c28749e9Skais 	if (mac_sz != 0) {
1724c28749e9Skais 		ASSERT(mp->b_wptr + mac_sz <= mp->b_datap->db_lim);
1725c28749e9Skais 		ret = kssl_compute_record_mac(ssl, KSSL_WRITE,
1726c28749e9Skais 		    ssl->seq_num[KSSL_WRITE], ct, versionp,
1727c28749e9Skais 		    rstart + SSL3_HDR_LEN, rec_sz, mp->b_wptr);
1728c28749e9Skais 		if (ret == CRYPTO_SUCCESS) {
1729c28749e9Skais 			ssl->seq_num[KSSL_WRITE]++;
1730c28749e9Skais 			mp->b_wptr += mac_sz;
1731c28749e9Skais 			rec_sz += mac_sz;
1732c28749e9Skais 		} else {
1733c28749e9Skais 			return (ret);
1734c28749e9Skais 		}
1735c28749e9Skais 	}
1736c28749e9Skais 
1737c28749e9Skais 	if (spec->cipher_type == type_block) {
1738c28749e9Skais 		pad_sz = spec->cipher_bsize -
1739c28749e9Skais 		    (rec_sz & (spec->cipher_bsize - 1));
1740c28749e9Skais 		ASSERT(mp->b_wptr + pad_sz <= mp->b_datap->db_lim);
1741c28749e9Skais 		for (i = 0; i < pad_sz; i++) {
1742c28749e9Skais 			mp->b_wptr[i] = pad_sz - 1;
1743c28749e9Skais 		}
1744c28749e9Skais 		mp->b_wptr += pad_sz;
1745c28749e9Skais 		rec_sz += pad_sz;
1746c28749e9Skais 	}
1747c28749e9Skais 
1748c28749e9Skais 	ASSERT(rec_sz <= SSL3_MAX_RECORD_LENGTH);
1749c28749e9Skais 
1750c28749e9Skais 	U16_TO_BE16(rec_sz, rstart + 3);
1751c28749e9Skais 
1752c28749e9Skais 	if (spec->cipher_ctx == 0)
1753c28749e9Skais 		return (ret);
1754c28749e9Skais 
1755c28749e9Skais 	spec->cipher_data.cd_length = rec_sz;
1756c28749e9Skais 	spec->cipher_data.cd_raw.iov_base = (char *)(rstart + SSL3_HDR_LEN);
1757c28749e9Skais 	spec->cipher_data.cd_raw.iov_len = rec_sz;
1758c28749e9Skais 	/* One record at a time. Otherwise, gotta allocate the crypt_data_t */
1759c28749e9Skais 	ret = crypto_encrypt_update(spec->cipher_ctx, &spec->cipher_data,
1760c28749e9Skais 	    NULL, NULL);
1761c28749e9Skais 	if (CRYPTO_ERR(ret)) {
176251dd2c77Svk199839 		DTRACE_PROBE1(kssl_err__crypto_encrypt_update,
176351dd2c77Svk199839 		    int, ret);
1764c28749e9Skais 	}
1765c28749e9Skais 	return (ret);
1766c28749e9Skais }
1767c28749e9Skais 
17687dd0d8ffSVladimir Kotal /*
17697dd0d8ffSVladimir Kotal  * Produce SSL alert message (SSLv3/TLS) or error message (SSLv2). For SSLv2
17707dd0d8ffSVladimir Kotal  * it is only done to tear down the SSL connection so it has fixed encoding.
17717dd0d8ffSVladimir Kotal  */
1772c28749e9Skais void
1773c28749e9Skais kssl_send_alert(ssl_t *ssl, SSL3AlertLevel level, SSL3AlertDescription desc)
1774c28749e9Skais {
1775c28749e9Skais 	mblk_t *mp;
1776c28749e9Skais 	uchar_t *buf;
1777c28749e9Skais 	KSSLCipherSpec *spec;
17787dd0d8ffSVladimir Kotal 	size_t len;
1779c28749e9Skais 
1780c28749e9Skais 	ASSERT(ssl != NULL);
1781c28749e9Skais 
1782c28749e9Skais 	ssl->sendalert_level = level;
1783c28749e9Skais 	ssl->sendalert_desc = desc;
1784c28749e9Skais 
1785c28749e9Skais 	if (level == alert_fatal) {
178651dd2c77Svk199839 		DTRACE_PROBE2(kssl_sending_alert,
178751dd2c77Svk199839 		    SSL3AlertLevel, level, SSL3AlertDescription, desc);
1788c28749e9Skais 		if (ssl->sid.cached == B_TRUE) {
1789c28749e9Skais 			kssl_uncache_sid(&ssl->sid, ssl->kssl_entry);
1790c28749e9Skais 		}
1791c28749e9Skais 		ssl->fatal_alert = B_TRUE;
1792c28749e9Skais 		KSSL_COUNTER(fatal_alerts, 1);
1793c28749e9Skais 	} else
1794c28749e9Skais 		KSSL_COUNTER(warning_alerts, 1);
1795c28749e9Skais 
1796c28749e9Skais 	spec = &ssl->spec[KSSL_WRITE];
1797c28749e9Skais 
1798c28749e9Skais 	ASSERT(ssl->alert_sendbuf == NULL);
1799*9b1bd49fSVladimir Kotal 	if (ssl->major_version == 0x03) {
1800*9b1bd49fSVladimir Kotal 		len = SSL3_HDR_LEN + SSL3_ALERT_LEN;
1801*9b1bd49fSVladimir Kotal 	} else {
1802*9b1bd49fSVladimir Kotal 		/* KSSL generates 5 byte SSLv2 alert messages only. */
18037dd0d8ffSVladimir Kotal 		len = 5;
1804*9b1bd49fSVladimir Kotal 	}
18057dd0d8ffSVladimir Kotal 	ssl->alert_sendbuf = mp = allocb(len + spec->mac_hashsz +
1806c28749e9Skais 	    spec->cipher_bsize, BPRI_HI);
1807c28749e9Skais 	if (mp == NULL) {
1808c28749e9Skais 		KSSL_COUNTER(alloc_fails, 1);
1809c28749e9Skais 		return;
1810c28749e9Skais 	}
1811c28749e9Skais 	buf = mp->b_wptr;
1812c28749e9Skais 
18137dd0d8ffSVladimir Kotal 	/* SSLv3/TLS */
18147dd0d8ffSVladimir Kotal 	if (ssl->major_version == 0x03) {
1815c28749e9Skais 		/* 5 byte record header */
1816c28749e9Skais 		buf[0] = content_alert;
1817c28749e9Skais 		buf[1] = ssl->major_version;
1818c28749e9Skais 		buf[2] = ssl->minor_version;
1819c28749e9Skais 		buf[3] = 0;
1820c28749e9Skais 		buf[4] = 2;
1821c28749e9Skais 		buf += SSL3_HDR_LEN;
1822c28749e9Skais 
1823c28749e9Skais 		/* alert contents */
1824c28749e9Skais 		buf[0] = (uchar_t)level;
1825c28749e9Skais 		buf[1] = (uchar_t)desc;
1826*9b1bd49fSVladimir Kotal 		buf += SSL3_ALERT_LEN;
18277dd0d8ffSVladimir Kotal 	} else {
18287dd0d8ffSVladimir Kotal 	/* SSLv2 has different encoding. */
18297dd0d8ffSVladimir Kotal 		/* 2-byte encoding of the length */
18307dd0d8ffSVladimir Kotal 		buf[0] = 0x80;
18317dd0d8ffSVladimir Kotal 		buf[1] = 0x03;
18327dd0d8ffSVladimir Kotal 		buf += 2;
1833c28749e9Skais 
18347dd0d8ffSVladimir Kotal 		/* Protocol Message Code = Error */
18357dd0d8ffSVladimir Kotal 		buf[0] = 0;
18367dd0d8ffSVladimir Kotal 		/* Error Message Code = Undefined Error */
18377dd0d8ffSVladimir Kotal 		buf[1] = 0;
18387dd0d8ffSVladimir Kotal 		buf[2] = 0;
18397dd0d8ffSVladimir Kotal 		buf += 3;
18407dd0d8ffSVladimir Kotal 	}
18417dd0d8ffSVladimir Kotal 
18427dd0d8ffSVladimir Kotal 	mp->b_wptr = buf;
1843c28749e9Skais }
1844c28749e9Skais 
1845c28749e9Skais /* Assumes RSA encryption */
1846c28749e9Skais static int
1847c28749e9Skais kssl_handle_client_key_exchange(ssl_t *ssl, mblk_t *mp, int msglen,
1848c28749e9Skais     kssl_callback_t cbfn, void *arg)
1849c28749e9Skais {
1850c28749e9Skais 	char *buf;
1851c28749e9Skais 	uchar_t *pms;
1852c28749e9Skais 	size_t pmslen;
1853c28749e9Skais 	int allocated;
1854c892ebf1Skrishna 	int err, rverr = ENOMEM;
1855c892ebf1Skrishna 	kssl_entry_t *ep;
1856c28749e9Skais 	crypto_key_t *privkey;
1857c28749e9Skais 	crypto_data_t *wrapped_pms_data, *pms_data;
1858c28749e9Skais 	crypto_call_req_t creq, *creqp;
1859c28749e9Skais 
1860c892ebf1Skrishna 	ep = ssl->kssl_entry;
1861c892ebf1Skrishna 	privkey = ep->ke_private_key;
1862c28749e9Skais 	if (privkey == NULL) {
1863c28749e9Skais 		return (ENOENT);
1864c28749e9Skais 	}
1865c28749e9Skais 
1866c28749e9Skais 	ASSERT(ssl->msg.type == client_key_exchange);
1867c28749e9Skais 	ASSERT(ssl->hs_waitstate == wait_client_key);
1868c28749e9Skais 
1869c28749e9Skais 	/*
1870c28749e9Skais 	 * TLS adds an extra 2 byte length field before the data.
1871c28749e9Skais 	 */
1872c28749e9Skais 	if (IS_TLS(ssl)) {
1873c28749e9Skais 		msglen = (mp->b_rptr[0] << 8) | mp->b_rptr[1];
1874c28749e9Skais 		mp->b_rptr += 2;
1875c28749e9Skais 	}
1876c28749e9Skais 
1877c28749e9Skais 	/*
1878c28749e9Skais 	 * Allocate all we need in one shot. about 300 bytes total, for
1879c28749e9Skais 	 * 1024 bit RSA modulus.
1880c28749e9Skais 	 * The buffer layout will be: pms_data, wrapped_pms_data, the
1881c28749e9Skais 	 * value of the wrapped pms from the client, then room for the
1882c28749e9Skais 	 * resulting decrypted premaster secret.
1883c28749e9Skais 	 */
1884c28749e9Skais 	allocated = 2 * (sizeof (crypto_data_t) + msglen);
1885c28749e9Skais 	buf = kmem_alloc(allocated, KM_NOSLEEP);
1886c28749e9Skais 	if (buf == NULL) {
1887c28749e9Skais 		return (ENOMEM);
1888c28749e9Skais 	}
1889c28749e9Skais 
1890c28749e9Skais 	pms_data = (crypto_data_t *)buf;
1891c28749e9Skais 	wrapped_pms_data = &(((crypto_data_t *)buf)[1]);
1892c28749e9Skais 
1893c28749e9Skais 	wrapped_pms_data->cd_format = pms_data->cd_format = CRYPTO_DATA_RAW;
1894c28749e9Skais 	wrapped_pms_data->cd_offset = pms_data->cd_offset = 0;
1895c28749e9Skais 	wrapped_pms_data->cd_length = pms_data->cd_length = msglen;
1896c28749e9Skais 	wrapped_pms_data->cd_miscdata = pms_data->cd_miscdata = NULL;
1897c28749e9Skais 	wrapped_pms_data->cd_raw.iov_len = pms_data->cd_raw.iov_len = msglen;
1898c28749e9Skais 	wrapped_pms_data->cd_raw.iov_base = buf + 2 * sizeof (crypto_data_t);
1899c28749e9Skais 	pms_data->cd_raw.iov_base = wrapped_pms_data->cd_raw.iov_base + msglen;
1900c28749e9Skais 
1901c28749e9Skais 	bcopy(mp->b_rptr, wrapped_pms_data->cd_raw.iov_base, msglen);
1902c28749e9Skais 	mp->b_rptr += msglen;
1903c28749e9Skais 
1904c28749e9Skais 	/* Proceed synchronously if out of interrupt and configured to do so */
1905c28749e9Skais 	if ((kssl_synchronous) && (!servicing_interrupt())) {
1906c28749e9Skais 		creqp = NULL;
1907c28749e9Skais 	} else {
1908c28749e9Skais 		ssl->cke_callback_func = cbfn;
1909c28749e9Skais 		ssl->cke_callback_arg = arg;
1910c28749e9Skais 		creq.cr_flag = kssl_call_flag;
1911c28749e9Skais 		creq.cr_callback_func = kssl_cke_done;
1912c28749e9Skais 		creq.cr_callback_arg = ssl;
1913c28749e9Skais 
1914c28749e9Skais 		creqp = &creq;
1915c28749e9Skais 	}
1916c28749e9Skais 
1917c892ebf1Skrishna 	if (ep->ke_is_nxkey) {
1918c892ebf1Skrishna 		kssl_session_info_t *s;
1919c892ebf1Skrishna 
1920c892ebf1Skrishna 		s = ep->ke_sessinfo;
1921c892ebf1Skrishna 		err = CRYPTO_SUCCESS;
1922c892ebf1Skrishna 		if (!s->is_valid_handle) {
1923c892ebf1Skrishna 			/* Reauthenticate to the provider */
1924c892ebf1Skrishna 			if (s->do_reauth) {
1925c892ebf1Skrishna 				err = kssl_get_obj_handle(ep);
1926c892ebf1Skrishna 				if (err == CRYPTO_SUCCESS) {
1927c892ebf1Skrishna 					s->is_valid_handle = B_TRUE;
1928c892ebf1Skrishna 					s->do_reauth = B_FALSE;
1929c892ebf1Skrishna 				}
1930c892ebf1Skrishna 			} else
1931c892ebf1Skrishna 				err = CRYPTO_FAILED;
1932c892ebf1Skrishna 		}
1933c892ebf1Skrishna 
1934c892ebf1Skrishna 		if (err == CRYPTO_SUCCESS) {
1935c892ebf1Skrishna 			ASSERT(s->is_valid_handle);
1936c892ebf1Skrishna 			err = crypto_decrypt_prov(s->prov, s->sid,
1937c892ebf1Skrishna 			    &rsa_x509_mech, wrapped_pms_data, &s->key,
1938c892ebf1Skrishna 			    NULL, pms_data, creqp);
1939c892ebf1Skrishna 		}
1940c892ebf1Skrishna 
1941c892ebf1Skrishna 		/*
1942c892ebf1Skrishna 		 * Deal with session specific errors. We translate to
1943c892ebf1Skrishna 		 * the closest errno.
1944c892ebf1Skrishna 		 */
1945c892ebf1Skrishna 		switch (err) {
1946c892ebf1Skrishna 		case CRYPTO_KEY_HANDLE_INVALID:
1947c892ebf1Skrishna 		case CRYPTO_SESSION_HANDLE_INVALID:
1948c892ebf1Skrishna 			s->is_valid_handle = B_FALSE;
1949c892ebf1Skrishna 			s->do_reauth = B_TRUE;
1950c892ebf1Skrishna 			rverr = EINVAL;
1951c892ebf1Skrishna 			break;
1952c892ebf1Skrishna 		case CRYPTO_PIN_EXPIRED:
1953c892ebf1Skrishna 		case CRYPTO_PIN_LOCKED:
1954c892ebf1Skrishna 			rverr = EACCES;
1955c892ebf1Skrishna 			break;
1956c892ebf1Skrishna 		case CRYPTO_UNKNOWN_PROVIDER:
1957c892ebf1Skrishna 			rverr = ENXIO;
1958c892ebf1Skrishna 			break;
1959c892ebf1Skrishna 		}
1960c892ebf1Skrishna 	} else {
1961c28749e9Skais 		err = crypto_decrypt(&rsa_x509_mech, wrapped_pms_data,
1962c28749e9Skais 		    privkey, NULL, pms_data, creqp);
1963c892ebf1Skrishna 	}
1964c28749e9Skais 
1965c28749e9Skais 	switch (err) {
1966c28749e9Skais 	case CRYPTO_SUCCESS:
1967c28749e9Skais 		break;
1968c28749e9Skais 
1969c28749e9Skais 	case CRYPTO_QUEUED:
1970c28749e9Skais 		/*
1971c28749e9Skais 		 * Finish the master secret then the rest of key material
1972c28749e9Skais 		 * derivation later.
1973c28749e9Skais 		 */
1974c28749e9Skais 		ssl->job.kjob = creq.cr_reqid;
1975c28749e9Skais 		ssl->job.buf = buf;
1976c28749e9Skais 		ssl->job.buflen = allocated;
1977c28749e9Skais 		ssl->hs_waitstate = wait_client_key_done;
1978c28749e9Skais 		return (0);
1979c28749e9Skais 	default:
198051dd2c77Svk199839 		DTRACE_PROBE1(kssl_err__crypto_decrypt, int, err);
1981c28749e9Skais 		kmem_free(buf, allocated);
1982c892ebf1Skrishna 		return (rverr);
1983c28749e9Skais 	}
1984c28749e9Skais 
1985c28749e9Skais 	pmslen = pms_data->cd_length;
1986c28749e9Skais 	pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen);
1987c28749e9Skais 
1988c28749e9Skais 	/* generate master key and save it in the ssl sid structure */
1989c28749e9Skais 	if (IS_TLS(ssl)) {
1990c28749e9Skais 		err = kssl_generate_tls_ms(ssl, pms, pmslen);
1991c28749e9Skais 		if (!CRYPTO_ERR(err))
1992c28749e9Skais 			err = kssl_generate_tls_keyblock(ssl);
1993c28749e9Skais 	} else {
1994c28749e9Skais 		kssl_generate_ssl_ms(ssl, pms, pmslen);
1995c28749e9Skais 		kssl_generate_keyblock(ssl);
1996c28749e9Skais 	}
1997c28749e9Skais 
1998c28749e9Skais 	if (err == CRYPTO_SUCCESS)
1999c28749e9Skais 		ssl->hs_waitstate = wait_change_cipher;
2000c28749e9Skais 
2001c28749e9Skais 	ssl->activeinput = B_FALSE;
2002c28749e9Skais 
2003c28749e9Skais 	kmem_free(buf, allocated);
2004c28749e9Skais 
2005c28749e9Skais 	return (0);
2006c28749e9Skais }
2007c28749e9Skais 
2008c28749e9Skais static int
2009c28749e9Skais kssl_handle_finished(ssl_t *ssl, mblk_t *mp, int msglen)
2010c28749e9Skais {
2011c28749e9Skais 	int err;
2012c28749e9Skais 	size_t finish_len;
2013c28749e9Skais 	int hashcompare;
2014c28749e9Skais 
2015c28749e9Skais 	ASSERT(ssl->msg.type == finished);
2016c28749e9Skais 	ASSERT(ssl->hs_waitstate == wait_finished);
2017c28749e9Skais 
2018c28749e9Skais 	if (IS_TLS(ssl))
2019c28749e9Skais 		finish_len = TLS_FINISHED_SIZE;
2020c28749e9Skais 	else
2021c28749e9Skais 		finish_len = KSSL_SSL3_FIN_MSGLEN;
2022c28749e9Skais 
2023c28749e9Skais 	if (msglen != finish_len) {
2024c28749e9Skais 		kssl_send_alert(ssl, alert_fatal, illegal_parameter);
2025c28749e9Skais 		return (EBADMSG);
2026c28749e9Skais 	}
2027c28749e9Skais 
2028c28749e9Skais 	if (IS_TLS(ssl)) {
2029c28749e9Skais 		hashcompare = bcmp(mp->b_rptr, ssl->hs_hashes.tlshash,
2030c28749e9Skais 		    finish_len);
2031c28749e9Skais 	} else {
2032c28749e9Skais 		hashcompare = bcmp(mp->b_rptr, &ssl->hs_hashes, finish_len);
2033c28749e9Skais 	}
2034c28749e9Skais 
2035c28749e9Skais 	/* The handshake hashes should be computed by now */
2036c28749e9Skais 	if (hashcompare != 0) {
2037c28749e9Skais 		kssl_send_alert(ssl, alert_fatal, handshake_failure);
2038c28749e9Skais 		return (EBADMSG);
2039c28749e9Skais 	}
2040c28749e9Skais 
2041c28749e9Skais 	mp->b_rptr += msglen;
2042c28749e9Skais 
2043c28749e9Skais 	ssl->hs_waitstate = idle_handshake;
2044c28749e9Skais 
2045c28749e9Skais 	if (ssl->resumed == B_TRUE) {
2046c28749e9Skais 		ssl->activeinput = B_FALSE;
2047c28749e9Skais 		return (0);
2048c28749e9Skais 	}
2049c28749e9Skais 
2050c28749e9Skais 	err = kssl_send_change_cipher_specs(ssl);
2051c28749e9Skais 	if (err != 0) {
2052c28749e9Skais 		return (err);
2053c28749e9Skais 	}
2054c28749e9Skais 	err = kssl_send_finished(ssl, 0);
2055c28749e9Skais 	if (err != 0) {
2056c28749e9Skais 		return (err);
2057c28749e9Skais 	}
2058c28749e9Skais 
2059c28749e9Skais 	kssl_cache_sid(&ssl->sid, ssl->kssl_entry);
2060c28749e9Skais 	ssl->activeinput = B_FALSE;
2061c28749e9Skais 
2062c28749e9Skais 	return (0);
2063c28749e9Skais }
2064c28749e9Skais 
2065c28749e9Skais #define	KSSL2_CH_MIN_RECSZ	(9)
2066c28749e9Skais 
2067c28749e9Skais /*
2068c28749e9Skais  * This method is needed to handle clients which send the
2069c28749e9Skais  * SSLv2/SSLv3 handshake for backwards compat with SSLv2 servers.
2070c28749e9Skais  * We are not really doing SSLv2 here, just handling the header
2071c28749e9Skais  * and then switching to SSLv3.
2072c28749e9Skais  */
2073c28749e9Skais int
2074c28749e9Skais kssl_handle_v2client_hello(ssl_t *ssl, mblk_t *mp, int recsz)
2075c28749e9Skais {
2076c28749e9Skais 	uchar_t *recend;
2077c28749e9Skais 	int err;
2078c28749e9Skais 	SSL3AlertDescription desc = illegal_parameter;
2079c28749e9Skais 	uint_t randlen;
2080c28749e9Skais 	uint_t sidlen;
208151144063SKrishna Yenduri 	uint_t cslen;
2082c28749e9Skais 	uchar_t *suitesp;
2083c28749e9Skais 	uchar_t *rand;
2084c28749e9Skais 	uint_t i, j;
208511d0a659SVladimir Kotal 	uint16_t suite, selected_suite;
2086c28749e9Skais 	int ch_recsz = KSSL2_CH_MIN_RECSZ;
208711d0a659SVladimir Kotal 	boolean_t suite_found = B_FALSE;
2088c28749e9Skais 
2089c28749e9Skais 	ASSERT(mp->b_wptr >= mp->b_rptr + recsz);
2090c28749e9Skais 	ASSERT(ssl->hs_waitstate == wait_client_hello);
2091c28749e9Skais 	ASSERT(ssl->resumed == B_FALSE);
2092c28749e9Skais 
2093c28749e9Skais 	if (recsz < ch_recsz) {
209465d18457SVladimir Kotal 		DTRACE_PROBE2(kssl_err__reclen_less_than_minimum,
209565d18457SVladimir Kotal 		    int, recsz, int, ch_recsz);
2096c28749e9Skais 		goto falert;
2097c28749e9Skais 	}
2098c28749e9Skais 
2099c28749e9Skais 	MD5Init(&ssl->hs_md5);
2100c28749e9Skais 	SHA1Init(&ssl->hs_sha1);
2101c28749e9Skais 
2102c28749e9Skais 	kssl_update_handshake_hashes(ssl, mp->b_rptr, recsz);
2103c28749e9Skais 
2104c28749e9Skais 	recend = mp->b_rptr + recsz;
2105c28749e9Skais 
2106c28749e9Skais 	if (*mp->b_rptr != 1) {
210765d18457SVladimir Kotal 		DTRACE_PROBE1(kssl_err__invalid_version, uint_t, *mp->b_rptr);
2108c28749e9Skais 		goto falert;
2109c28749e9Skais 	}
2110c28749e9Skais 	mp->b_rptr += 3;
2111c28749e9Skais 
211251144063SKrishna Yenduri 	cslen = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1];
2113c28749e9Skais 	sidlen = ((uint_t)mp->b_rptr[2] << 8) + (uint_t)mp->b_rptr[3];
2114c28749e9Skais 	randlen = ((uint_t)mp->b_rptr[4] << 8) + (uint_t)mp->b_rptr[5];
211551144063SKrishna Yenduri 	if (cslen % 3 != 0) {
211651144063SKrishna Yenduri 		DTRACE_PROBE1(kssl_err__cipher_suites_len_error, uint_t, cslen);
2117c28749e9Skais 		goto falert;
2118c28749e9Skais 	}
2119c28749e9Skais 	if (randlen < SSL_MIN_CHALLENGE_BYTES ||
2120c28749e9Skais 	    randlen > SSL_MAX_CHALLENGE_BYTES) {
212151dd2c77Svk199839 		DTRACE_PROBE1(kssl_err__randlen_out_of_range,
212251dd2c77Svk199839 		    uint_t, randlen);
2123c28749e9Skais 		goto falert;
2124c28749e9Skais 	}
2125c28749e9Skais 	mp->b_rptr += 6;
212651144063SKrishna Yenduri 	ch_recsz += cslen + sidlen + randlen;
2127c28749e9Skais 	if (recsz != ch_recsz) {
212865d18457SVladimir Kotal 		DTRACE_PROBE2(kssl_err__invalid_message_len_sum,
212965d18457SVladimir Kotal 		    int, recsz, int, ch_recsz);
2130c28749e9Skais 		goto falert;
2131c28749e9Skais 	}
2132c28749e9Skais 	suitesp = mp->b_rptr;
213351144063SKrishna Yenduri 	rand = suitesp + cslen + sidlen;
2134c28749e9Skais 	if (randlen < SSL3_RANDOM_LENGTH) {
2135c28749e9Skais 		bzero(ssl->client_random, SSL3_RANDOM_LENGTH);
2136c28749e9Skais 	}
2137c28749e9Skais 	bcopy(rand, &ssl->client_random[SSL3_RANDOM_LENGTH - randlen],
2138c28749e9Skais 	    randlen);
2139c28749e9Skais 
2140c28749e9Skais 	for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) {
2141c28749e9Skais 		suite = ssl->kssl_entry->kssl_cipherSuites[i];
214251144063SKrishna Yenduri 		for (j = 0; j < cslen; j += 3) {
214311d0a659SVladimir Kotal 			DTRACE_PROBE2(kssl_cipher_suite_check_v2,
214411d0a659SVladimir Kotal 			    uint16_t, suite,
214511d0a659SVladimir Kotal 			    uint16_t,
214611d0a659SVladimir Kotal 			    (uint16_t)((suitesp[j+1] << 8) + suitesp[j+2]));
2147c28749e9Skais 			if (suitesp[j] != 0) {
2148c28749e9Skais 				continue;
2149c28749e9Skais 			}
2150c28749e9Skais 
215111d0a659SVladimir Kotal 			/* Check for regular (true) cipher suite. */
2152c28749e9Skais 			if (suitesp[j + 1] == ((suite >> 8) & 0xff) &&
2153c28749e9Skais 			    suitesp[j + 2] == (suite & 0xff)) {
215411d0a659SVladimir Kotal 				DTRACE_PROBE1(kssl_cipher_suite_found,
215511d0a659SVladimir Kotal 				    uint16_t, suite);
215611d0a659SVladimir Kotal 				suite_found = B_TRUE;
215711d0a659SVladimir Kotal 				selected_suite = suite;
215811d0a659SVladimir Kotal 			}
215911d0a659SVladimir Kotal 
216011d0a659SVladimir Kotal 			/* Check for SCSV. */
216111d0a659SVladimir Kotal 			if (suitesp[j + 1] ==  ((SSL_SCSV >> 8) & 0xff) &&
216211d0a659SVladimir Kotal 			    suitesp[j + 2] == (SSL_SCSV & 0xff)) {
216311d0a659SVladimir Kotal 				DTRACE_PROBE(kssl_scsv_found);
216411d0a659SVladimir Kotal 				ssl->secure_renegotiation = B_TRUE;
216511d0a659SVladimir Kotal 			}
216611d0a659SVladimir Kotal 			/*
216711d0a659SVladimir Kotal 			 * If we got cipher suite match and SCSV or went
216811d0a659SVladimir Kotal 			 * through the whole list of client cipher suites
216911d0a659SVladimir Kotal 			 * (hence we know if SCSV was present or not) we
217011d0a659SVladimir Kotal 			 * can terminate the cycle now.
217111d0a659SVladimir Kotal 			 */
217211d0a659SVladimir Kotal 			if (suite_found &&
217311d0a659SVladimir Kotal 			    (ssl->secure_renegotiation || (i > 0)))
2174c28749e9Skais 				break;
2175c28749e9Skais 		}
217611d0a659SVladimir Kotal 		if (suite_found)
2177c28749e9Skais 			break;
2178c28749e9Skais 	}
217911d0a659SVladimir Kotal 	if (!suite_found) {
218051dd2c77Svk199839 		DTRACE_PROBE(kssl_err__no_SSLv2_cipher_suite);
2181c28749e9Skais 		ssl->activeinput = B_FALSE;
218265d18457SVladimir Kotal 		/*
218365d18457SVladimir Kotal 		 * If there is no fallback point terminate the handshake with
218465d18457SVladimir Kotal 		 * SSL alert otherwise return with SSL_MISS.
218565d18457SVladimir Kotal 		 */
218665d18457SVladimir Kotal 		if (ssl->kssl_entry->ke_fallback_head == NULL) {
218765d18457SVladimir Kotal 			DTRACE_PROBE(kssl_no_fallback);
218865d18457SVladimir Kotal 			desc = handshake_failure;
218965d18457SVladimir Kotal 			goto falert;
219065d18457SVladimir Kotal 		} else {
2191c28749e9Skais 			return (SSL_MISS);
2192c28749e9Skais 		}
219365d18457SVladimir Kotal 	}
2194c28749e9Skais 
2195c28749e9Skais 	mp->b_rptr = recend;
2196c28749e9Skais 
2197c28749e9Skais 	for (i = 0; i < cipher_suite_defs_nentries; i++) {
219811d0a659SVladimir Kotal 		if (selected_suite == cipher_suite_defs[i].suite) {
2199c28749e9Skais 			break;
2200c28749e9Skais 		}
2201c28749e9Skais 	}
2202c28749e9Skais 
2203c28749e9Skais 	ASSERT(i < cipher_suite_defs_nentries);
2204c28749e9Skais 
220511d0a659SVladimir Kotal 	ssl->pending_cipher_suite = selected_suite;
2206c28749e9Skais 	ssl->pending_malg = cipher_suite_defs[i].malg;
2207c28749e9Skais 	ssl->pending_calg = cipher_suite_defs[i].calg;
2208c28749e9Skais 	ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz;
2209c28749e9Skais 
2210c28749e9Skais 	ASSERT(ssl->sid.cached == B_FALSE);
2211c28749e9Skais 
2212c28749e9Skais 	(void) random_get_pseudo_bytes(ssl->sid.session_id,
2213c28749e9Skais 	    SSL3_SESSIONID_BYTES);
2214c28749e9Skais 	ssl->sid.client_addr = ssl->faddr;
221511d0a659SVladimir Kotal 	ssl->sid.cipher_suite = selected_suite;
2216c28749e9Skais 
2217c28749e9Skais 	err = kssl_send_server_hello(ssl);
2218c28749e9Skais 	if (err != 0) {
2219c28749e9Skais 		return (err);
2220c28749e9Skais 	}
2221c28749e9Skais 	err = kssl_send_certificate_and_server_hello_done(ssl);
2222c28749e9Skais 	if (err != 0) {
2223c28749e9Skais 		return (err);
2224c28749e9Skais 	}
2225c28749e9Skais 	KSSL_COUNTER(full_handshakes, 1);
2226c28749e9Skais 	ssl->hs_waitstate = wait_client_key;
2227c28749e9Skais 	ssl->activeinput = B_FALSE;
2228c28749e9Skais 	return (0);
2229c28749e9Skais 
2230c28749e9Skais falert:
2231c28749e9Skais 	kssl_send_alert(ssl, alert_fatal, desc);
2232c28749e9Skais 	ssl->activeinput = B_FALSE;
2233c28749e9Skais 	return (EBADMSG);
2234c28749e9Skais }
2235c28749e9Skais 
2236c28749e9Skais /*
2237c28749e9Skais  * Call back routine for asynchronously submitted RSA decryption jobs.
223851144063SKrishna Yenduri  * This routine retrieves the pre-master secret, and proceeds to generate
2239c28749e9Skais  * the remaining key materials.
2240c28749e9Skais  */
2241c28749e9Skais static void
2242c28749e9Skais kssl_cke_done(void *arg, int status)
2243c28749e9Skais {
2244c28749e9Skais 	int ret = 0;
2245c28749e9Skais 	uchar_t *pms;
2246c28749e9Skais 	size_t pmslen;
2247c28749e9Skais 	crypto_data_t *pms_data;
2248c28749e9Skais 	kssl_cmd_t kssl_cmd = KSSL_CMD_NONE;
2249c28749e9Skais 	ssl_t *ssl = (ssl_t *)arg;
2250c28749e9Skais 	mblk_t *alertmp;
2251c28749e9Skais 	kssl_callback_t cbfn;
2252c28749e9Skais 	void *cbarg;
2253c28749e9Skais 
2254c28749e9Skais 	mutex_enter(&ssl->kssl_lock);
2255c28749e9Skais 
2256c28749e9Skais 	ASSERT(ssl->msg.type == client_key_exchange);
2257c28749e9Skais 	ASSERT(ssl->hs_waitstate == wait_client_key_done);
2258c28749e9Skais 
2259c28749e9Skais 	if (status != CRYPTO_SUCCESS) {
2260c28749e9Skais 		kssl_send_alert(ssl, alert_fatal, decrypt_error);
2261c28749e9Skais 		kssl_cmd = KSSL_CMD_SEND;
2262c28749e9Skais 		goto out;
2263c28749e9Skais 	}
2264c28749e9Skais 
2265c28749e9Skais 	pms_data = (crypto_data_t *)(ssl->job.buf);
2266c28749e9Skais 
2267c28749e9Skais 	ASSERT(pms_data != NULL);
2268c28749e9Skais 
2269c28749e9Skais 	pmslen = pms_data->cd_length;
2270c28749e9Skais 	pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen);
2271c28749e9Skais 
2272c28749e9Skais 	/* generate master key and save it in the ssl sid structure */
2273c28749e9Skais 	if (IS_TLS(ssl)) {
2274c28749e9Skais 		ret = kssl_generate_tls_ms(ssl, pms, pmslen);
2275c28749e9Skais 		if (!CRYPTO_ERR(ret))
2276c28749e9Skais 			ret = kssl_generate_tls_keyblock(ssl);
2277c28749e9Skais 	} else {
2278c28749e9Skais 		kssl_generate_ssl_ms(ssl, pms, pmslen);
2279c28749e9Skais 		kssl_generate_keyblock(ssl);
2280c28749e9Skais 	}
2281c28749e9Skais 
2282c28749e9Skais 	if (ret == CRYPTO_SUCCESS)
2283c28749e9Skais 		ssl->hs_waitstate = wait_change_cipher;
2284c28749e9Skais 
2285c28749e9Skais out:
2286c28749e9Skais 	kmem_free(ssl->job.buf, ssl->job.buflen);
2287c28749e9Skais 
2288c28749e9Skais 	ssl->job.kjob = 0;
2289c28749e9Skais 	ssl->job.buf = NULL;
2290c28749e9Skais 	ssl->job.buflen = 0;
2291c28749e9Skais 
2292c28749e9Skais 	ssl->activeinput = B_FALSE;
2293c28749e9Skais 
2294c28749e9Skais 	cbfn = ssl->cke_callback_func;
2295c28749e9Skais 	cbarg = ssl->cke_callback_arg;
2296c28749e9Skais 	alertmp = ssl->alert_sendbuf;
2297c28749e9Skais 	ssl->alert_sendbuf = NULL;
2298c28749e9Skais 
2299dd49f125SAnders Persson 	/* dropped by callback when it has completed */
2300dd49f125SAnders Persson 	ssl->async_ops_pending++;
2301c28749e9Skais 	mutex_exit(&ssl->kssl_lock);
2302c28749e9Skais 
2303c28749e9Skais 	/* Now call the callback routine */
2304c28749e9Skais 	(*(cbfn))(cbarg, alertmp, kssl_cmd);
2305c28749e9Skais }
2306c28749e9Skais 
2307c28749e9Skais /*
2308c28749e9Skais  * Returns the first complete contiguous record out of rec_ass_head
2309c28749e9Skais  * The record is returned in a separate contiguous mblk, rec_ass_head is
2310c28749e9Skais  * left pointing to the next record in the queue.
2311c28749e9Skais  *
2312c28749e9Skais  * The output looks as follows:
2313c28749e9Skais  *
2314c28749e9Skais  * |--------|---------- .... -----|<---------->|<----------->|--- ... ---|
2315c28749e9Skais  * ^        ^                     ^  mac_size     pad_size               ^
2316c28749e9Skais  * |        |___ b_rptr  b_wptr __|                                      |
2317c28749e9Skais  * |                                                                     |
2318c28749e9Skais  * |___ db_base                                                db_lim ___|
2319c28749e9Skais  */
2320c28749e9Skais mblk_t *
2321c28749e9Skais kssl_get_next_record(ssl_t *ssl)
2322c28749e9Skais {
2323c28749e9Skais 	mblk_t *mp, *retmp;
2324c28749e9Skais 	int rhsz = SSL3_HDR_LEN;
2325c28749e9Skais 	uint16_t rec_sz;
2326c28749e9Skais 	int mpsz, total_size;
2327c28749e9Skais 	SSL3ContentType content_type;
2328c28749e9Skais 
2329c28749e9Skais 	ASSERT(MUTEX_HELD(&ssl->kssl_lock));
2330c28749e9Skais 
2331c28749e9Skais 	mp = ssl->rec_ass_head;
2332c28749e9Skais 	if (mp == NULL)
2333c28749e9Skais 		return (NULL);
2334c28749e9Skais 
2335c28749e9Skais 	/* Fast path: when mp has at least a complete record */
2336c28749e9Skais 	if (MBLKL(mp) < rhsz) {
233751dd2c77Svk199839 		DTRACE_PROBE1(kssl_mblk__incomplete_header,
233851dd2c77Svk199839 		    mblk_t *, mp);
2339c28749e9Skais 		/* Not even a complete header in there yet */
2340c28749e9Skais 		if (msgdsize(mp) < rhsz) {
2341c28749e9Skais 			return (NULL);
2342c28749e9Skais 		}
2343c28749e9Skais 
2344c28749e9Skais 		if (!pullupmsg(mp, rhsz)) {
2345c28749e9Skais 			kssl_send_alert(ssl, alert_fatal, internal_error);
2346c28749e9Skais 			freemsg(mp);
2347c28749e9Skais 			ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
2348c28749e9Skais 			return (NULL);
2349c28749e9Skais 		}
2350c28749e9Skais 	}
2351c28749e9Skais 	content_type = (SSL3ContentType)mp->b_rptr[0];
2352c28749e9Skais 	if (content_type == content_handshake_v2) {
235351dd2c77Svk199839 		DTRACE_PROBE1(kssl_mblk__ssl_v2, mblk_t *, mp);
2354c28749e9Skais 		rec_sz = (uint16_t)mp->b_rptr[1];
2355c28749e9Skais 		rhsz = 2;
2356c28749e9Skais 	} else {
235751dd2c77Svk199839 		DTRACE_PROBE1(kssl_mblk__ssl_v3, mblk_t *, mp);
2358c28749e9Skais 		uint8_t *rec_sz_p = (uint8_t *)mp->b_rptr + 3;
2359c28749e9Skais 		rec_sz = BE16_TO_U16(rec_sz_p);
2360c28749e9Skais 	}
2361c28749e9Skais 
2362c28749e9Skais 	/*
2363c28749e9Skais 	 * same tests as above. Only rare very fragmented cases will
2364c28749e9Skais 	 * incur the cost of msgdsize() and msgpullup(). Well formed
2365c28749e9Skais 	 * packets will fall in the most frequent fast path.
2366c28749e9Skais 	 */
2367c28749e9Skais 	total_size = rhsz + rec_sz;
2368c28749e9Skais 
2369c28749e9Skais 	/*
2370c28749e9Skais 	 * Missing: defensive against record fabricated with longer than
2371c28749e9Skais 	 * MAX record length.
2372c28749e9Skais 	 */
2373c28749e9Skais 	if (MBLKL(mp) < total_size) {
237451dd2c77Svk199839 		DTRACE_PROBE2(kssl_mblk__smaller_than_total_size,
237551dd2c77Svk199839 		    mblk_t *, mp, int, total_size);
2376c28749e9Skais 		/* Not a complete record yet. Keep accumulating */
2377c28749e9Skais 		if (msgdsize(mp) < total_size) {
2378c28749e9Skais 			return (NULL);
2379c28749e9Skais 		}
2380c28749e9Skais 
2381c28749e9Skais 		if (!pullupmsg(mp, total_size)) {
2382c28749e9Skais 			kssl_send_alert(ssl, alert_fatal, internal_error);
2383c28749e9Skais 			freemsg(mp);
2384c28749e9Skais 			ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
2385c28749e9Skais 			return (NULL);
2386c28749e9Skais 		}
2387c28749e9Skais 	}
2388c28749e9Skais 	mpsz = MBLKL(mp);	/* could've changed after the pullup */
2389c28749e9Skais 
2390c28749e9Skais 	if (mpsz > total_size) {
239151dd2c77Svk199839 		DTRACE_PROBE2(kssl_mblk__bigger_than_total_size,
239251dd2c77Svk199839 		    mblk_t *, mp, int, total_size);
2393c28749e9Skais 		/* gotta allocate a new block */
2394c28749e9Skais 		if ((retmp = dupb(mp)) == NULL) {
2395c28749e9Skais 			kssl_send_alert(ssl, alert_fatal, internal_error);
2396c28749e9Skais 			freemsg(mp);
2397c28749e9Skais 			ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
2398c28749e9Skais 			return (NULL);
2399c28749e9Skais 		}
2400c28749e9Skais 
2401c28749e9Skais 		retmp->b_wptr = retmp->b_rptr + total_size;
2402c28749e9Skais 		mp->b_rptr += total_size;
2403c28749e9Skais 		ssl->rec_ass_head = mp;
2404c28749e9Skais 	} else {
240551dd2c77Svk199839 		DTRACE_PROBE2(kssl_mblk__equal_to_total_size,
240651dd2c77Svk199839 		    mblk_t *, mp, int, total_size);
2407c28749e9Skais 		ASSERT(mpsz == total_size);
2408c28749e9Skais 		ssl->rec_ass_head = mp->b_cont;
2409c28749e9Skais 		mp->b_cont = NULL;
2410c28749e9Skais 		retmp = mp;
2411c28749e9Skais 	}
2412c28749e9Skais 	/* Adjust the tail */
2413c28749e9Skais 	if ((mp = ssl->rec_ass_tail = ssl->rec_ass_head) != NULL) {
2414c28749e9Skais 		for (; mp->b_cont != NULL; mp = mp->b_cont) {
2415c28749e9Skais 			ssl->rec_ass_tail = mp->b_cont;
2416c28749e9Skais 		}
2417c28749e9Skais 	}
2418c28749e9Skais 
2419c28749e9Skais 	return (retmp);
2420c28749e9Skais }
2421c28749e9Skais 
2422c28749e9Skais 
2423c28749e9Skais static void
2424c28749e9Skais kssl_mblksfree(ssl_t *ssl)
2425c28749e9Skais {
2426c28749e9Skais 
2427c28749e9Skais 	ASSERT(ssl != NULL);
2428c28749e9Skais 
2429c28749e9Skais 	if (ssl->rec_ass_head != NULL) {
2430c28749e9Skais 		freemsg(ssl->rec_ass_head);
2431c28749e9Skais 	}
2432c28749e9Skais 	ssl->rec_ass_head = NULL;
2433c28749e9Skais 	ssl->rec_ass_tail = NULL;
2434c28749e9Skais 
2435c28749e9Skais 	if (ssl->msg.head != NULL) {
2436c28749e9Skais 		freemsg(ssl->msg.head);
2437c28749e9Skais 	}
2438c28749e9Skais 	ssl->msg.head = NULL;
2439c28749e9Skais 	ssl->msg.tail = NULL;
2440c28749e9Skais 
2441c28749e9Skais 	if (ssl->handshake_sendbuf != NULL) {
2442c28749e9Skais 		freemsg(ssl->handshake_sendbuf);
2443c28749e9Skais 		ssl->handshake_sendbuf = NULL;
2444c28749e9Skais 	}
2445c28749e9Skais 	if (ssl->alert_sendbuf != NULL) {
2446c28749e9Skais 		freemsg(ssl->alert_sendbuf);
2447c28749e9Skais 		ssl->alert_sendbuf = NULL;
2448c28749e9Skais 	}
2449c28749e9Skais }
2450c28749e9Skais 
2451c28749e9Skais static void
2452c28749e9Skais kssl_specsfree(ssl_t *ssl)
2453c28749e9Skais {
2454c28749e9Skais 	KSSLCipherSpec *spec = &ssl->spec[KSSL_READ];
2455c28749e9Skais 
2456c28749e9Skais 	if (spec->cipher_ctx != NULL) {
2457c28749e9Skais 		crypto_cancel_ctx(spec->cipher_ctx);
2458c28749e9Skais 		spec->cipher_ctx = 0;
2459c28749e9Skais 	}
2460c28749e9Skais 
2461c28749e9Skais 	spec = &ssl->spec[KSSL_WRITE];
2462c28749e9Skais 
2463c28749e9Skais 	if (spec->cipher_ctx != NULL) {
2464c28749e9Skais 		crypto_cancel_ctx(spec->cipher_ctx);
2465c28749e9Skais 		spec->cipher_ctx = 0;
2466c28749e9Skais 	}
2467c28749e9Skais }
2468c28749e9Skais 
2469c28749e9Skais /*
2470c28749e9Skais  * Frees the ssl structure (aka the context of an SSL session).
2471c28749e9Skais  * Any pending crypto jobs are cancelled.
2472c28749e9Skais  * Any initiated crypto contexts are freed as well.
2473c28749e9Skais  */
2474c28749e9Skais void
2475c28749e9Skais kssl_free_context(ssl_t *ssl)
2476c28749e9Skais {
2477dd49f125SAnders Persson 	crypto_req_id_t reqid;
2478dd49f125SAnders Persson 
2479c28749e9Skais 	ASSERT(ssl != NULL);
2480c28749e9Skais 	if (!(MUTEX_HELD(&ssl->kssl_lock))) {
2481c28749e9Skais 		/* we're coming from an external API entry point */
2482c28749e9Skais 		mutex_enter(&ssl->kssl_lock);
2483c28749e9Skais 	}
2484c28749e9Skais 
2485dd49f125SAnders Persson 	/*
2486dd49f125SAnders Persson 	 * Cancel any active crypto request and wait for pending async
2487dd49f125SAnders Persson 	 * operations to complete. We loop here because the async thread
2488dd49f125SAnders Persson 	 * might submit a new cryto request.
2489dd49f125SAnders Persson 	 */
2490dd49f125SAnders Persson 	do {
2491c28749e9Skais 		if (ssl->job.kjob != NULL) {
2492dd49f125SAnders Persson 			/*
2493dd49f125SAnders Persson 			 * Drop the lock before canceling the request;
2494dd49f125SAnders Persson 			 * otherwise we might deadlock if the completion
2495dd49f125SAnders Persson 			 * callback is running.
2496dd49f125SAnders Persson 			 */
2497dd49f125SAnders Persson 			reqid = ssl->job.kjob;
2498dd49f125SAnders Persson 			mutex_exit(&ssl->kssl_lock);
2499dd49f125SAnders Persson 			crypto_cancel_req(reqid);
2500dd49f125SAnders Persson 			mutex_enter(&ssl->kssl_lock);
2501c28749e9Skais 
2502dd49f125SAnders Persson 			/* completion callback might have done the cleanup */
2503dd49f125SAnders Persson 			if (ssl->job.kjob != NULL) {
2504dd49f125SAnders Persson 				kmem_free(ssl->job.buf, ssl->job.buflen);
2505c28749e9Skais 				ssl->job.kjob = 0;
2506c28749e9Skais 				ssl->job.buf = NULL;
2507c28749e9Skais 				ssl->job.buflen = 0;
2508c28749e9Skais 			}
2509dd49f125SAnders Persson 		}
2510dd49f125SAnders Persson 		while (ssl->async_ops_pending > 0)
2511dd49f125SAnders Persson 			cv_wait(&ssl->async_cv, &ssl->kssl_lock);
2512dd49f125SAnders Persson 	} while (ssl->job.kjob != NULL);
2513c28749e9Skais 
2514c28749e9Skais 	kssl_mblksfree(ssl);
2515c28749e9Skais 	kssl_specsfree(ssl);
2516c28749e9Skais 
2517c28749e9Skais 	KSSL_ENTRY_REFRELE(ssl->kssl_entry);
2518c28749e9Skais 	ssl->kssl_entry = NULL;
2519c28749e9Skais 
2520c28749e9Skais 	mutex_exit(&ssl->kssl_lock);
2521c28749e9Skais 
2522c28749e9Skais 	kmem_cache_free(kssl_cache, ssl);
2523c28749e9Skais }
2524