xref: /onnv-gate/usr/src/uts/common/inet/kssl/ksslrec.c (revision 4859:0da5a5774596)
1898Skais /*
2898Skais  * CDDL HEADER START
3898Skais  *
4898Skais  * The contents of this file are subject to the terms of the
51724Skrishna  * Common Development and Distribution License (the "License").
61724Skrishna  * You may not use this file except in compliance with the License.
7898Skais  *
8898Skais  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9898Skais  * or http://www.opensolaris.org/os/licensing.
10898Skais  * See the License for the specific language governing permissions
11898Skais  * and limitations under the License.
12898Skais  *
13898Skais  * When distributing Covered Code, include this CDDL HEADER in each
14898Skais  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15898Skais  * If applicable, add the following below this CDDL HEADER, with the
16898Skais  * fields enclosed by brackets "[]" replaced with your own identifying
17898Skais  * information: Portions Copyright [yyyy] [name of copyright owner]
18898Skais  *
19898Skais  * CDDL HEADER END
20898Skais  */
21898Skais /*
22*4859Skrishna  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23898Skais  * Use is subject to license terms.
24898Skais  */
25898Skais 
26898Skais #pragma ident	"%Z%%M%	%I%	%E% SMI"
27898Skais 
28898Skais #include <sys/types.h>
29898Skais #include <sys/stream.h>
30898Skais #include <sys/strsubr.h>
31898Skais #include <sys/stropts.h>
32898Skais #include <sys/strsun.h>
33898Skais #define	_SUN_TPI_VERSION 2
34898Skais #include <sys/ddi.h>
35898Skais #include <sys/sunddi.h>
36898Skais #include <sys/cmn_err.h>
37898Skais #include <sys/debug.h>
38898Skais #include <sys/vtrace.h>
39898Skais #include <sys/kmem.h>
40898Skais #include <sys/cpuvar.h>
41898Skais #include <sys/atomic.h>
42898Skais #include <sys/sysmacros.h>
43898Skais 
44898Skais #include <sys/errno.h>
45898Skais #include <sys/isa_defs.h>
46898Skais #include <sys/md5.h>
47898Skais #include <sys/sha1.h>
48898Skais #include <sys/random.h>
49898Skais #include <inet/common.h>
50898Skais #include <netinet/in.h>
51898Skais 
52898Skais #include <sys/systm.h>
53898Skais #include <sys/param.h>
54898Skais 
55898Skais #include "ksslimpl.h"
56898Skais #include "ksslapi.h"
57898Skais #include "ksslproto.h"
58898Skais #include "kssldebug.h"
59898Skais 
60898Skais static ssl3CipherSuiteDef cipher_suite_defs[] = {
61898Skais 	{SSL_RSA_WITH_RC4_128_SHA,	cipher_rc4,	mac_sha,	72},
62898Skais 	{SSL_RSA_WITH_RC4_128_MD5,	cipher_rc4,	mac_md5,	64},
63898Skais 	{SSL_RSA_WITH_DES_CBC_SHA,	cipher_des,	mac_sha,	72},
64898Skais 	{SSL_RSA_WITH_3DES_EDE_CBC_SHA,	cipher_3des,	mac_sha,	104},
65898Skais 	{SSL_RSA_WITH_NULL_SHA,		cipher_null,	mac_sha,	40}
66898Skais };
67898Skais 
68898Skais static int cipher_suite_defs_nentries =
69898Skais     sizeof (cipher_suite_defs) / sizeof (cipher_suite_defs[0]);
70898Skais 
71898Skais static KSSLMACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */
72898Skais 	/* macsz padsz HashInit HashUpdate HashFinal */
73898Skais 
74898Skais 	{MD5_HASH_LEN, SSL3_MD5_PAD_LEN,
75898Skais 	    (hashinit_func_t)MD5Init, (hashupdate_func_t)MD5Update,
76898Skais 	    (hashfinal_func_t)MD5Final},
77898Skais 
78898Skais 	{SHA1_HASH_LEN, SSL3_SHA1_PAD_LEN,
79898Skais 	    (hashinit_func_t)SHA1Init, (hashupdate_func_t)SHA1Update,
80898Skais 	    (hashfinal_func_t)SHA1Final},
81898Skais };
82898Skais 
83898Skais static uchar_t kssl_pad_1[60] = {
84898Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
85898Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
86898Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
87898Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
88898Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
89898Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
90898Skais     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
91898Skais     0x36, 0x36, 0x36, 0x36
92898Skais };
93898Skais static uchar_t kssl_pad_2[60] = {
94898Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
95898Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
96898Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
97898Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
98898Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
99898Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
100898Skais     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
101898Skais     0x5c, 0x5c, 0x5c, 0x5c
102898Skais };
103898Skais 
104898Skais int kssl_debug;
105898Skais int kssl_cache_count;
106898Skais static boolean_t kssl_synchronous = B_FALSE;
107898Skais 
108898Skais static void kssl_update_handshake_hashes(ssl_t *, uchar_t *, uint_t);
109898Skais static int kssl_compute_handshake_hashes(ssl_t *, SSL3Hashes *, uint32_t);
110898Skais static int kssl_handle_client_hello(ssl_t *, mblk_t *, int);
111898Skais static int kssl_handle_client_key_exchange(ssl_t *, mblk_t *, int,
112898Skais     kssl_callback_t, void *);
113898Skais static int kssl_send_server_hello(ssl_t *);
114898Skais static int kssl_send_certificate_and_server_hello_done(ssl_t *);
115898Skais static int kssl_send_change_cipher_specs(ssl_t *);
116898Skais static int kssl_send_finished(ssl_t *, int);
117898Skais static int kssl_handle_finished(ssl_t *, mblk_t *, int);
118898Skais static void kssl_get_hello_random(uchar_t *);
119898Skais static uchar_t *kssl_rsa_unwrap(uchar_t *, size_t *);
120898Skais static void kssl_cache_sid(sslSessionID *, kssl_entry_t *);
121898Skais static void kssl_lookup_sid(sslSessionID *, uchar_t *, ipaddr_t,
122898Skais     kssl_entry_t *);
123898Skais static int kssl_generate_tls_ms(ssl_t *, uchar_t *, size_t);
124898Skais static void kssl_generate_ssl_ms(ssl_t *, uchar_t *, size_t);
125898Skais static int kssl_generate_tls_keyblock(ssl_t *);
126898Skais static void kssl_generate_keyblock(ssl_t *);
127898Skais static void kssl_ssl3_key_material_derive_step(ssl_t *, uchar_t *, size_t,
128898Skais     int, uchar_t *, int);
129898Skais static int kssl_tls_PRF(ssl_t *, uchar_t *, size_t,
130898Skais     uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t);
131898Skais static int kssl_tls_P_hash(crypto_mechanism_t *, crypto_key_t *,
132898Skais     size_t, uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t);
133898Skais static void kssl_cke_done(void *, int);
134898Skais 
135898Skais #define	MAX_TLS_KEYBLOCK_SIZE 160 /* more than enough for largest TLS key */
136898Skais 
137898Skais #define	HMAC_INIT(m, k, c) \
138898Skais 	rv = crypto_mac_init(m, k, NULL, c, NULL); if (CRYPTO_ERR(rv)) goto end;
139898Skais 
140898Skais #define	HMAC_UPDATE(c, d, l) \
141898Skais 	dd.cd_raw.iov_base = (char *)d; \
142898Skais 	dd.cd_length = dd.cd_raw.iov_len = l; \
143898Skais 	rv = crypto_mac_update(c, &dd, NULL); if (CRYPTO_ERR(rv)) goto end;
144898Skais 
145898Skais #define	HMAC_FINAL(c, d, l) \
146898Skais 	mac.cd_raw.iov_base = (char *)d; \
147898Skais 	mac.cd_length = mac.cd_raw.iov_len = l; \
148898Skais 	rv = crypto_mac_final(c, &mac, NULL); if (CRYPTO_ERR(rv)) goto end;
149898Skais 
150*4859Skrishna /*
151*4859Skrishna  * This hack can go away once we have SSL3 MAC support by KCF
152*4859Skrishna  * software providers (See 4873559).
153*4859Skrishna  */
154*4859Skrishna extern int kcf_md5_threshold;
155*4859Skrishna 
156898Skais int
157898Skais kssl_compute_record_mac(
158898Skais 	ssl_t *ssl,
159898Skais 	int direction,
160898Skais 	uint64_t seq_num,
161898Skais 	SSL3ContentType ct,
162898Skais 	uchar_t *versionp,
163898Skais 	uchar_t *buf,
164898Skais 	int len,
165898Skais 	uchar_t *digest)
166898Skais {
167898Skais 	KSSL_HASHCTX mac_ctx;
168898Skais 	KSSL_HASHCTX *ctx = &mac_ctx;
169898Skais 	uchar_t temp[16], *p;
170898Skais 	KSSLCipherSpec *spec;
171*4859Skrishna 	boolean_t hash_use_ok = B_FALSE;
172898Skais 	int rv = 0;
173898Skais 
174898Skais 	spec = &ssl->spec[direction];
175898Skais 
176898Skais 	if (spec->mac_hashsz == 0) {
177898Skais 		return (1);
178898Skais 	}
179898Skais 
180898Skais 	p = temp;
181898Skais 
182898Skais 	*p++ = (seq_num >> 56) & 0xff;
183898Skais 	*p++ = (seq_num >> 48) & 0xff;
184898Skais 	*p++ = (seq_num >> 40) & 0xff;
185898Skais 	*p++ = (seq_num >> 32) & 0xff;
186898Skais 	*p++ = (seq_num >> 24) & 0xff;
187898Skais 	*p++ = (seq_num >> 16) & 0xff;
188898Skais 	*p++ = (seq_num >> 8) & 0xff;
189898Skais 	*p++ = (seq_num) & 0xff;
190898Skais 	*p++ = (uchar_t)ct;
191898Skais 	if (IS_TLS(ssl)) {
192898Skais 		*p++ = versionp[0];
193898Skais 		*p++ = versionp[1];
194898Skais 	}
195898Skais 	*p++ = (len >> 8) & 0xff;
196898Skais 	*p++ = (len) & 0xff;
197898Skais 
198*4859Skrishna 	if (IS_TLS(ssl) || (spec->hmac_mech.cm_type != CRYPTO_MECH_INVALID &&
199*4859Skrishna 	    len >= kcf_md5_threshold)) {
200898Skais 		crypto_data_t dd, mac;
201*4859Skrishna 		struct uio uio_pt;
202*4859Skrishna 		struct iovec iovarray_pt[2];
203*4859Skrishna 
204*4859Skrishna 		/* init the array of iovecs for use in the uio struct */
205*4859Skrishna 		iovarray_pt[0].iov_base = (char *)temp;
206*4859Skrishna 		iovarray_pt[0].iov_len = (p - temp);
207*4859Skrishna 		iovarray_pt[1].iov_base = (char *)buf;
208*4859Skrishna 		iovarray_pt[1].iov_len = len;
209898Skais 
210*4859Skrishna 		/* init the uio struct for use in the crypto_data_t struct */
211*4859Skrishna 		bzero(&uio_pt, sizeof (uio_pt));
212*4859Skrishna 		uio_pt.uio_iov = iovarray_pt;
213*4859Skrishna 		uio_pt.uio_iovcnt = 2;
214*4859Skrishna 		uio_pt.uio_segflg = UIO_SYSSPACE;
215*4859Skrishna 
216*4859Skrishna 		dd.cd_format = CRYPTO_DATA_UIO;
217898Skais 		dd.cd_offset = 0;
218*4859Skrishna 		dd.cd_length =  (p - temp) + len;
219*4859Skrishna 		dd.cd_miscdata = NULL;
220*4859Skrishna 		dd.cd_uio = &uio_pt;
221*4859Skrishna 
222898Skais 		mac.cd_format = CRYPTO_DATA_RAW;
223898Skais 		mac.cd_offset = 0;
224*4859Skrishna 		mac.cd_raw.iov_base = (char *)digest;
225*4859Skrishna 		mac.cd_length = mac.cd_raw.iov_len = spec->mac_hashsz;
226898Skais 
227*4859Skrishna 		/*
228*4859Skrishna 		 * The calling context can tolerate a blocking call here.
229*4859Skrishna 		 * For outgoing traffic, we are in user context
230*4859Skrishna 		 * when called from strsock_kssl_output(). For incoming
231*4859Skrishna 		 * traffic past the SSL handshake, we are in user
232*4859Skrishna 		 * context when called from strsock_kssl_input(). During the
233*4859Skrishna 		 * SSL handshake, we are called for client_finished message
234*4859Skrishna 		 * handling from a squeue worker thread that gets scheduled
235*4859Skrishna 		 * by an squeue_fill() call. This thread is not in interrupt
236*4859Skrishna 		 * context and so can block.
237*4859Skrishna 		 */
238*4859Skrishna 		rv = crypto_mac(&spec->hmac_mech, &dd, &spec->hmac_key,
239*4859Skrishna 		    NULL, &mac, NULL);
240*4859Skrishna 
241898Skais 		if (CRYPTO_ERR(rv)) {
242*4859Skrishna 			hash_use_ok = (rv == CRYPTO_MECH_NOT_SUPPORTED &&
243*4859Skrishna 			    !IS_TLS(ssl));
244*4859Skrishna 			if (!hash_use_ok) {
245898Skais #ifdef	DEBUG
246*4859Skrishna 				cmn_err(CE_WARN, "kssl_compute_record_mac - "
247*4859Skrishna 				    "crypto_mac error 0x%0x", rv);
248898Skais #endif	/* DEBUG */
249*4859Skrishna 				KSSL_COUNTER(compute_mac_failure, 1);
250*4859Skrishna 			}
251898Skais 		}
252*4859Skrishna 	} else
253*4859Skrishna 		hash_use_ok = B_TRUE;
254*4859Skrishna 
255*4859Skrishna 	if (hash_use_ok) {
256898Skais 		bcopy(&(ssl->mac_ctx[direction][0]), ctx,
257898Skais 			sizeof (KSSL_HASHCTX));
258898Skais 		spec->MAC_HashUpdate((void *)ctx, temp, p - temp);
259898Skais 		spec->MAC_HashUpdate((void *)ctx, buf, len);
260898Skais 		spec->MAC_HashFinal(digest, (void *)ctx);
261898Skais 
262898Skais 		bcopy(&(ssl->mac_ctx[direction][1]), ctx,
263898Skais 			sizeof (KSSL_HASHCTX));
264898Skais 		spec->MAC_HashUpdate((void *)ctx, digest, spec->mac_hashsz);
265898Skais 		spec->MAC_HashFinal(digest, (void *)ctx);
266898Skais 	}
267898Skais 
268898Skais 	return (rv);
269898Skais }
270898Skais 
271898Skais /*
272898Skais  * Handles handshake messages.
273898Skais  * Messages to be replied are returned in handshake_sendbuf.
274898Skais  */
275898Skais int
276898Skais kssl_handle_handshake_message(ssl_t *ssl, mblk_t *mp, int *err,
277898Skais     kssl_callback_t cbfn, void *arg)
278898Skais {
279898Skais 	uint32_t msglen;
280898Skais 	uchar_t msghdr[4];
281898Skais 
282898Skais 	ASSERT(ssl->msg.state == MSG_BODY);
283898Skais 	ASSERT(ssl->msg.msglen_bytes == 3);
284898Skais 	ASSERT(mp->b_wptr >= mp->b_rptr + ssl->msg.msglen);
285898Skais 
286898Skais 	ssl->sslcnt++;
287898Skais 	msglen = ssl->msg.msglen;
288898Skais 
289898Skais 	if (ssl->msg.type == client_hello) {
290898Skais 		MD5Init(&ssl->hs_md5);
291898Skais 		SHA1Init(&ssl->hs_sha1);
292898Skais 	}
293898Skais 
294898Skais 	if (ssl->msg.type == finished && ssl->resumed == B_FALSE) {
295898Skais 		if (kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes,
296898Skais 		    sender_client) != 0) {
297898Skais 			*err = SSL_MISS;
298898Skais 			return (0);
299898Skais 		}
300898Skais 	}
301898Skais 
302898Skais 	if (ssl->msg.type != finished || ssl->resumed == B_FALSE) {
303898Skais 		msghdr[0] = (uchar_t)ssl->msg.type;
304898Skais 
305898Skais 		msghdr[1] = (uchar_t)(msglen >> 16);
306898Skais 		msghdr[2] = (uchar_t)(msglen >> 8);
307898Skais 		msghdr[3] = (uchar_t)(msglen);
308898Skais 		kssl_update_handshake_hashes(ssl, msghdr, 4);
309898Skais 		kssl_update_handshake_hashes(ssl, mp->b_rptr, msglen);
310898Skais 	}
311898Skais 
312898Skais 	ssl->msg.state = MSG_INIT;
313898Skais 	ssl->msg.msglen = 0;
314898Skais 	ssl->msg.msglen_bytes = 0;
315898Skais 
316898Skais 	switch (ssl->msg.type) {
317898Skais 	case client_hello:
318898Skais 		if (ssl->hs_waitstate != wait_client_hello) {
319898Skais 			kssl_send_alert(ssl, alert_fatal,
320898Skais 			    unexpected_message);
321898Skais 			*err = EBADMSG;
322898Skais 			ssl->activeinput = B_FALSE;
323898Skais 			return (1);
324898Skais 		}
325898Skais 		*err = kssl_handle_client_hello(ssl, mp, msglen);
326898Skais 		if (*err == SSL_MISS) {
327898Skais 			ssl->activeinput = B_FALSE;
328898Skais 			return (0);
329898Skais 		}
330898Skais 		return (1);
331898Skais 	case client_key_exchange:
332898Skais 		if (ssl->hs_waitstate != wait_client_key) {
333898Skais 			kssl_send_alert(ssl, alert_fatal,
334898Skais 			    unexpected_message);
335898Skais 			*err = EBADMSG;
336898Skais 			ssl->activeinput = B_FALSE;
337898Skais 			return (1);
338898Skais 		}
339898Skais 		*err = kssl_handle_client_key_exchange(ssl, mp,
340898Skais 		    msglen, cbfn, arg);
341898Skais 		return (1);
342898Skais 	case finished:
343898Skais 		if (ssl->hs_waitstate != wait_finished) {
344898Skais 			kssl_send_alert(ssl, alert_fatal,
345898Skais 				unexpected_message);
346898Skais 			*err = EBADMSG;
347898Skais 			ssl->activeinput = B_FALSE;
348898Skais 			return (1);
349898Skais 		}
350898Skais 		*err = kssl_handle_finished(ssl, mp, msglen);
351898Skais 		return (1);
352898Skais 	default:
353898Skais 		kssl_send_alert(ssl, alert_fatal, unexpected_message);
354898Skais 		ssl->activeinput = B_FALSE;
355898Skais 		*err = EBADMSG;
356898Skais 		return (1);
357898Skais 	}
358898Skais }
359898Skais 
360898Skais static void
361898Skais kssl_update_handshake_hashes(ssl_t *ssl, uchar_t *buf, uint_t len)
362898Skais {
363898Skais 	MD5Update(&ssl->hs_md5, buf, len);
364898Skais 	SHA1Update(&ssl->hs_sha1, buf, len);
365898Skais }
366898Skais 
367898Skais static int
368898Skais kssl_compute_handshake_hashes(
369898Skais 	ssl_t *ssl,
370898Skais 	SSL3Hashes *hashes,
371898Skais 	uint32_t sender)
372898Skais {
373898Skais 	MD5_CTX md5 = ssl->hs_md5;	/* clone md5 context */
374898Skais 	SHA1_CTX sha1 = ssl->hs_sha1;	/* clone sha1 context */
375898Skais 	MD5_CTX *md5ctx = &md5;
376898Skais 	SHA1_CTX *sha1ctx = &sha1;
377898Skais 
378898Skais 	if (IS_TLS(ssl)) {
379898Skais 		uchar_t seed[MD5_HASH_LEN + SHA1_HASH_LEN];
380898Skais 		char *label;
381898Skais 
382898Skais 		/*
383898Skais 		 * Do not take another hash step here.
384898Skais 		 * Just complete the operation.
385898Skais 		 */
386898Skais 		MD5Final(hashes->md5, md5ctx);
387898Skais 		SHA1Final(hashes->sha1, sha1ctx);
388898Skais 
389898Skais 		bcopy(hashes->md5, seed, MD5_HASH_LEN);
390898Skais 		bcopy(hashes->sha1, seed + MD5_HASH_LEN, SHA1_HASH_LEN);
391898Skais 
392898Skais 		if (sender == sender_client)
393898Skais 			label = TLS_CLIENT_FINISHED_LABEL;
394898Skais 		else
395898Skais 			label = TLS_SERVER_FINISHED_LABEL;
396898Skais 
397898Skais 		return (kssl_tls_PRF(ssl,
398898Skais 			ssl->sid.master_secret, (size_t)SSL3_MASTER_SECRET_LEN,
399898Skais 			(uchar_t *)label, strlen(label),
400898Skais 			seed, (size_t)(MD5_HASH_LEN + SHA1_HASH_LEN),
401898Skais 			hashes->tlshash, (size_t)TLS_FINISHED_SIZE));
402898Skais 	} else {
403898Skais 		uchar_t s[4];
404898Skais 		s[0] = (sender >> 24) & 0xff;
405898Skais 		s[1] = (sender >> 16) & 0xff;
406898Skais 		s[2] = (sender >> 8) & 0xff;
407898Skais 		s[3] = (sender) & 0xff;
408898Skais 
409898Skais 		MD5Update(md5ctx, s, 4);
410898Skais 		MD5Update(md5ctx, ssl->sid.master_secret,
411898Skais 		    SSL3_MASTER_SECRET_LEN);
412898Skais 		MD5Update(md5ctx, kssl_pad_1, SSL3_MD5_PAD_LEN);
413898Skais 		MD5Final(hashes->md5, md5ctx);
414898Skais 
415898Skais 		MD5Init(md5ctx);
416898Skais 		MD5Update(md5ctx, ssl->sid.master_secret,
417898Skais 		    SSL3_MASTER_SECRET_LEN);
418898Skais 		MD5Update(md5ctx, kssl_pad_2, SSL3_MD5_PAD_LEN);
419898Skais 		MD5Update(md5ctx, hashes->md5, MD5_HASH_LEN);
420898Skais 		MD5Final(hashes->md5, md5ctx);
421898Skais 
422898Skais 		SHA1Update(sha1ctx, s, 4);
423898Skais 		SHA1Update(sha1ctx, ssl->sid.master_secret,
424898Skais 		    SSL3_MASTER_SECRET_LEN);
425898Skais 		SHA1Update(sha1ctx, kssl_pad_1, SSL3_SHA1_PAD_LEN);
426898Skais 		SHA1Final(hashes->sha1, sha1ctx);
427898Skais 
428898Skais 		SHA1Init(sha1ctx);
429898Skais 		SHA1Update(sha1ctx, ssl->sid.master_secret,
430898Skais 		    SSL3_MASTER_SECRET_LEN);
431898Skais 		SHA1Update(sha1ctx, kssl_pad_2, SSL3_SHA1_PAD_LEN);
432898Skais 		SHA1Update(sha1ctx, hashes->sha1, SHA1_HASH_LEN);
433898Skais 		SHA1Final(hashes->sha1, sha1ctx);
434898Skais 		return (0);
435898Skais 	}
436898Skais }
437898Skais 
438898Skais 
439898Skais #define	KSSL_SSL3_CH_MIN_MSGLEN	(39)
440898Skais 
441898Skais static int
442898Skais kssl_handle_client_hello(ssl_t *ssl, mblk_t *mp, int msglen)
443898Skais {
444898Skais 	uchar_t *msgend;
445898Skais 	int err;
446898Skais 	SSL3AlertDescription desc = illegal_parameter;
447898Skais 	uint_t sidlen;
448898Skais 	uint_t nsuites;
449898Skais 	uchar_t *suitesp;
450898Skais 	uint_t i, j;
451898Skais 	uint16_t suite;
452898Skais 	int ch_msglen = KSSL_SSL3_CH_MIN_MSGLEN;
453898Skais 
454898Skais 	ASSERT(mp->b_wptr >= mp->b_rptr + msglen);
455898Skais 	ASSERT(ssl->msg.type == client_hello);
456898Skais 	ASSERT(ssl->hs_waitstate == wait_client_hello);
457898Skais 	ASSERT(ssl->resumed == B_FALSE);
458898Skais 
459898Skais 	if (msglen < ch_msglen) {
460898Skais 		goto falert;
461898Skais 	}
462898Skais 
463898Skais 	msgend = mp->b_rptr + msglen;
464898Skais 
465898Skais 	/* Support SSLv3 (version == 3.0) or TLS (version == 3.1) */
466898Skais 	if (ssl->major_version != 3 || (ssl->major_version == 3 &&
467898Skais 		ssl->minor_version != 0 && ssl->minor_version != 1)) {
468898Skais 		KSSL_DEBUG3_IF(kssl_debug,
469898Skais 			"HandleClientHello: handshake failure - "
470898Skais 			"SSL version not supported (%d %d)",
471898Skais 			ssl->major_version, ssl->minor_version);
472898Skais 		desc = handshake_failure;
473898Skais 		goto falert;
474898Skais 	}
475898Skais 	mp->b_rptr += 2; /* skip the version bytes */
476898Skais 
477898Skais 	bcopy(mp->b_rptr, ssl->client_random, SSL3_RANDOM_LENGTH);
478898Skais 	mp->b_rptr += SSL3_RANDOM_LENGTH;
479898Skais 
480898Skais 	ASSERT(ssl->sid.cached == B_FALSE);
481898Skais 	sidlen = *mp->b_rptr++;
482898Skais 	ch_msglen += sidlen;
483898Skais 	if (msglen < ch_msglen) {
484898Skais 		goto falert;
485898Skais 	}
486898Skais 	if (sidlen != SSL3_SESSIONID_BYTES) {
487898Skais 		mp->b_rptr += sidlen;
488898Skais 	} else {
489898Skais 		kssl_lookup_sid(&ssl->sid, mp->b_rptr, ssl->faddr,
490898Skais 		    ssl->kssl_entry);
491898Skais 		mp->b_rptr += SSL3_SESSIONID_BYTES;
492898Skais 	}
493898Skais 
494898Skais 	nsuites = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1];
495898Skais 	mp->b_rptr += 2;
496898Skais 	ch_msglen += nsuites;
497898Skais 	if (msglen != ch_msglen) {
498898Skais 		goto falert;
499898Skais 	}
500898Skais 	if (nsuites & 0x1) {
501898Skais 		goto falert;
502898Skais 	}
503898Skais 	suitesp = mp->b_rptr;
504898Skais 	if (ssl->sid.cached == B_TRUE) {
505898Skais 		suite = ssl->sid.cipher_suite;
506898Skais 		for (j = 0; j < nsuites; j += 2) {
507898Skais 			if (suitesp[j] == ((suite >> 8) & 0xff) &&
508898Skais 			    suitesp[j + 1] == (suite & 0xff)) {
509898Skais 				break;
510898Skais 			}
511898Skais 		}
512898Skais 		if (j < nsuites) {
513898Skais 			goto suite_found;
514898Skais 		}
515898Skais 		kssl_uncache_sid(&ssl->sid, ssl->kssl_entry);
516898Skais 		ssl->sid.cached = B_FALSE;
517898Skais 	}
518898Skais 
519898Skais 	/* Check if this server is capable of the cipher suite */
520898Skais 	for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) {
521898Skais 		suite = ssl->kssl_entry->kssl_cipherSuites[i];
522898Skais 		for (j = 0; j < nsuites; j += 2) {
523898Skais 			if (suitesp[j] == ((suite >> 8) & 0xff) &&
524898Skais 			    suitesp[j + 1] == (suite & 0xff)) {
525898Skais 				break;
526898Skais 			}
527898Skais 		}
528898Skais 		if (j < nsuites) {
529898Skais 			break;
530898Skais 		}
531898Skais 	}
532898Skais 	if (i == ssl->kssl_entry->kssl_cipherSuites_nentries) {
533898Skais 		if (ssl->sslcnt == 1) {
534898Skais 			KSSL_COUNTER(no_suite_found, 1);
535898Skais 			return (SSL_MISS);
536898Skais 		}
537898Skais 		desc = handshake_failure;
538898Skais 		KSSL_DEBUG1_IF(kssl_debug,
539898Skais 			"kssl_handle_client_hello: no cipher suites found");
540898Skais 		goto falert;
541898Skais 	}
542898Skais 
543898Skais suite_found:
544898Skais 
545898Skais 	mp->b_rptr += nsuites;
546898Skais 	if (*mp->b_rptr++ != 1 || *mp->b_rptr++ != 0) {
547898Skais 		desc = handshake_failure;
548898Skais 		KSSL_DEBUG1_IF(kssl_debug,
549898Skais 			"kssl_handle_client_hello: handshake failure");
550898Skais 		goto falert;
551898Skais 	}
552898Skais 
553898Skais 	mp->b_rptr = msgend;
554898Skais 
555898Skais 	for (i = 0; i < cipher_suite_defs_nentries; i++) {
556898Skais 		if (suite == cipher_suite_defs[i].suite) {
557898Skais 			break;
558898Skais 		}
559898Skais 	}
560898Skais 
561898Skais 	ASSERT(i < cipher_suite_defs_nentries);
562898Skais 
563898Skais 	ssl->pending_cipher_suite = suite;
564898Skais 	ssl->pending_malg = cipher_suite_defs[i].malg;
565898Skais 	ssl->pending_calg = cipher_suite_defs[i].calg;
566898Skais 	ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz;
567898Skais 
568898Skais 	if (ssl->sid.cached == B_TRUE) {
569898Skais 		err = kssl_send_server_hello(ssl);
570898Skais 		if (err != 0) {
571898Skais 			return (err);
572898Skais 		}
573898Skais 		if (IS_TLS(ssl))
574898Skais 			err = kssl_generate_tls_keyblock(ssl);
575898Skais 		else
576898Skais 			kssl_generate_keyblock(ssl);
577898Skais 
578898Skais 		err = kssl_send_change_cipher_specs(ssl);
579898Skais 		if (err != 0) {
580898Skais 			return (err);
581898Skais 		}
582898Skais 
583898Skais 		err = kssl_send_finished(ssl, 1);
584898Skais 		if (err != 0)
585898Skais 			return (err);
586898Skais 
587898Skais 		err = kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes,
588898Skais 			sender_client);
589898Skais 		if (err != 0)
590898Skais 			return (err);
591898Skais 
592898Skais 		ssl->hs_waitstate = wait_change_cipher;
593898Skais 		ssl->resumed = B_TRUE;
594898Skais 		ssl->activeinput = B_FALSE;
595898Skais 		KSSL_COUNTER(resumed_sessions, 1);
596898Skais 		return (0);
597898Skais 	}
598898Skais 
599898Skais 	(void) random_get_pseudo_bytes(ssl->sid.session_id,
600898Skais 	    SSL3_SESSIONID_BYTES);
601898Skais 	ssl->sid.client_addr = ssl->faddr;
602898Skais 	ssl->sid.cipher_suite = suite;
603898Skais 
604898Skais 	err = kssl_send_server_hello(ssl);
605898Skais 	if (err != 0) {
606898Skais 		return (err);
607898Skais 	}
608898Skais 	err = kssl_send_certificate_and_server_hello_done(ssl);
609898Skais 	if (err != 0) {
610898Skais 		return (err);
611898Skais 	}
612898Skais 	KSSL_COUNTER(full_handshakes, 1);
613898Skais 	ssl->hs_waitstate = wait_client_key;
614898Skais 	ssl->activeinput = B_FALSE;
615898Skais 	return (0);
616898Skais 
617898Skais falert:
618898Skais 	kssl_send_alert(ssl, alert_fatal, desc);
619898Skais 	return (EBADMSG);
620898Skais }
621898Skais 
622898Skais static void
623898Skais kssl_cache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry)
624898Skais {
625898Skais 	uint_t index;
626898Skais 	uchar_t *s = sid->session_id;
627898Skais 	int l = SSL3_SESSIONID_BYTES - 1;
628898Skais 	kmutex_t *lock;
629898Skais 
630898Skais 	ASSERT(sid->cached == B_TRUE);
631898Skais 
632898Skais 	index = (int)sid->client_addr ^ (((int)s[0] << 24) | ((int)s[1] << 16) |
633898Skais 	    ((int)s[2] << 8) | (int)s[l]);
634898Skais 
635898Skais 	index %= kssl_entry->sid_cache_nentries;
636898Skais 
637898Skais 	sid->time = lbolt;
638898Skais 
639898Skais 	lock = &(kssl_entry->sid_cache[index].se_lock);
640898Skais 	mutex_enter(lock);
641898Skais 	kssl_entry->sid_cache[index].se_used++;
642898Skais 	bcopy(sid, &(kssl_entry->sid_cache[index].se_sid), sizeof (*sid));
643898Skais 	mutex_exit(lock);
644898Skais }
645898Skais 
646898Skais static void
647898Skais kssl_lookup_sid(sslSessionID *sid, uchar_t *s, ipaddr_t faddr,
648898Skais     kssl_entry_t *kssl_entry)
649898Skais {
650898Skais 	uint_t index;
651898Skais 	int l = SSL3_SESSIONID_BYTES - 1;
652898Skais 	kmutex_t *lock;
653898Skais 	sslSessionID *csid;
654898Skais 
655898Skais 	ASSERT(sid->cached == B_FALSE);
656898Skais 
657898Skais 	KSSL_COUNTER(sid_cache_lookups, 1);
658898Skais 
659898Skais 	index = (int)faddr ^ (((int)s[0] << 24) | ((int)s[1] << 16) |
660898Skais 	    ((int)s[2] << 8) | (int)s[l]);
661898Skais 
662898Skais 	index %= kssl_entry->sid_cache_nentries;
663898Skais 
664898Skais 	lock = &(kssl_entry->sid_cache[index].se_lock);
665898Skais 	mutex_enter(lock);
666898Skais 	csid = &(kssl_entry->sid_cache[index].se_sid);
667898Skais 	if (csid->cached == B_FALSE || csid->client_addr != faddr ||
668898Skais 	    bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) {
669898Skais 		mutex_exit(lock);
670898Skais 		return;
671898Skais 	}
672898Skais 
673898Skais 	if (TICK_TO_SEC(lbolt - csid->time) > kssl_entry->sid_cache_timeout) {
674898Skais 		csid->cached = B_FALSE;
675898Skais 		mutex_exit(lock);
676898Skais 		return;
677898Skais 	}
678898Skais 
679898Skais 	bcopy(csid, sid, sizeof (*sid));
680898Skais 	mutex_exit(lock);
681898Skais 	ASSERT(sid->cached == B_TRUE);
682898Skais 
683898Skais 	KSSL_COUNTER(sid_cache_hits, 1);
684898Skais }
685898Skais 
686898Skais static uchar_t *
687898Skais kssl_rsa_unwrap(uchar_t *buf, size_t *lenp)
688898Skais {
689898Skais 	size_t len = *lenp;
690898Skais 	int i = 2;
691898Skais 
692898Skais 	if (buf[0] != 0 || buf[1] != 2) {
693898Skais 		return (NULL);
694898Skais 	}
695898Skais 
696898Skais 	while (i < len) {
697898Skais 		if (buf[i++] == 0) {
698898Skais 			*lenp = len - i;
699898Skais 			break;
700898Skais 		}
701898Skais 	}
702898Skais 
703898Skais 	if (i == len) {
704898Skais 		return (NULL);
705898Skais 	}
706898Skais 
707898Skais 	return (buf + i);
708898Skais }
709898Skais 
710898Skais void
711898Skais kssl_uncache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry)
712898Skais {
713898Skais 	uint_t index;
714898Skais 	uchar_t *s = sid->session_id;
715898Skais 	int l = SSL3_SESSIONID_BYTES - 1;
716898Skais 	sslSessionID *csid;
717898Skais 	kmutex_t *lock;
718898Skais 
719898Skais 	ASSERT(sid->cached == B_TRUE);
720898Skais 
721898Skais 	KSSL_COUNTER(sid_uncached, 1);
722898Skais 
723898Skais 	index = (int)sid->client_addr ^ (((int)s[0] << 24) | ((int)s[1] << 16) |
724898Skais 	    ((int)s[2] << 8) | (int)s[l]);
725898Skais 
726898Skais 	index %= kssl_entry->sid_cache_nentries;
727898Skais 
728898Skais 	lock = &(kssl_entry->sid_cache[index].se_lock);
729898Skais 	mutex_enter(lock);
730898Skais 	csid = &(kssl_entry->sid_cache[index].se_sid);
731898Skais 	if (csid->client_addr != sid->client_addr ||
732898Skais 	    bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) {
733898Skais 		mutex_exit(lock);
734898Skais 		return;
735898Skais 	}
736898Skais 	csid->cached = B_FALSE;
737898Skais 	mutex_exit(lock);
738898Skais }
739898Skais 
740898Skais 
741898Skais #define	KSSL_SSL3_SH_RECLEN	(74)
742898Skais #define	KSSL_SSL3_FIN_MSGLEN	(36)
743898Skais 
744898Skais #define	KSSL_SSL3_MAX_CCP_FIN_MSGLEN	(128)	/* comfortable upper bound */
745898Skais 
746898Skais static int
747898Skais kssl_send_server_hello(ssl_t *ssl)
748898Skais {
749898Skais 	mblk_t *mp;
750898Skais 	uchar_t *buf;
751898Skais 	uchar_t *msgstart;
752898Skais 
753898Skais 	mp = allocb(ssl->tcp_mss, BPRI_HI);
754898Skais 	if (mp == NULL) {
755898Skais 		KSSL_COUNTER(alloc_fails, 1);
756898Skais 		return (ENOMEM);
757898Skais 	}
758898Skais 	ssl->handshake_sendbuf = mp;
759898Skais 	buf = mp->b_wptr;
760898Skais 
761898Skais 	/* 5 byte record header */
762898Skais 	buf[0] = content_handshake;
763898Skais 	buf[1] = ssl->major_version;
764898Skais 	buf[2] = ssl->minor_version;
765898Skais 	buf[3] = KSSL_SSL3_SH_RECLEN >> 8;
766898Skais 	buf[4] = KSSL_SSL3_SH_RECLEN & 0xff;
767898Skais 	buf += SSL3_HDR_LEN;
768898Skais 
769898Skais 	msgstart = buf;
770898Skais 
771898Skais 	/* 6 byte message header */
772898Skais 	buf[0] = (uchar_t)server_hello;			/* message type */
773898Skais 	buf[1] = 0;					/* message len byte 0 */
774898Skais 	buf[2] = ((KSSL_SSL3_SH_RECLEN - 4) >> 8) &
775898Skais 	    0xff;					/* message len byte 1 */
776898Skais 	buf[3] = (KSSL_SSL3_SH_RECLEN - 4) & 0xff;	/* message len byte 2 */
777898Skais 
778898Skais 	buf[4] = ssl->major_version;	/* version byte 0 */
779898Skais 	buf[5] = ssl->minor_version;	/* version byte 1 */
780898Skais 
781898Skais 	buf += 6;
782898Skais 
783898Skais 	kssl_get_hello_random(ssl->server_random);
784898Skais 	bcopy(ssl->server_random, buf, SSL3_RANDOM_LENGTH);
785898Skais 	buf += SSL3_RANDOM_LENGTH;
786898Skais 
787898Skais 	buf[0] = SSL3_SESSIONID_BYTES;
788898Skais 	bcopy(ssl->sid.session_id, buf + 1, SSL3_SESSIONID_BYTES);
789898Skais 	buf += SSL3_SESSIONID_BYTES + 1;
790898Skais 
791898Skais 	buf[0] = (ssl->pending_cipher_suite >> 8) & 0xff;
792898Skais 	buf[1] = ssl->pending_cipher_suite & 0xff;
793898Skais 
794898Skais 	buf[2] = 0;	/* No compression */
795898Skais 
796898Skais 	mp->b_wptr = buf + 3;
797898Skais 	ASSERT(mp->b_wptr < mp->b_datap->db_lim);
798898Skais 
799898Skais 	kssl_update_handshake_hashes(ssl, msgstart, KSSL_SSL3_SH_RECLEN);
800898Skais 	return (0);
801898Skais }
802898Skais 
803898Skais static void
804898Skais kssl_get_hello_random(uchar_t *buf)
805898Skais {
806898Skais 	timestruc_t ts;
807898Skais 	time_t sec;
808898Skais 
809898Skais 	gethrestime(&ts);
810898Skais 	sec = ts.tv_sec;
811898Skais 
812898Skais 	buf[0] = (sec >> 24) & 0xff;
813898Skais 	buf[1] = (sec >> 16) & 0xff;
814898Skais 	buf[2] = (sec >> 8) & 0xff;
815898Skais 	buf[3] = (sec) & 0xff;
816898Skais 
817898Skais 	(void) random_get_pseudo_bytes(&buf[4], SSL3_RANDOM_LENGTH - 4);
818898Skais 
819898Skais 	/* Should this be caching? */
820898Skais }
821898Skais 
822898Skais static int
823898Skais kssl_tls_P_hash(crypto_mechanism_t *mech, crypto_key_t *key,
824898Skais 	size_t hashlen,
825898Skais 	uchar_t *label, size_t label_len,
826898Skais 	uchar_t *seed, size_t seedlen,
827898Skais 	uchar_t *data, size_t datalen)
828898Skais {
829898Skais 	int rv = 0;
830898Skais 	uchar_t A1[MAX_HASH_LEN], result[MAX_HASH_LEN];
831898Skais 	int bytes_left = datalen;
832898Skais 	crypto_data_t dd, mac;
833898Skais 	crypto_context_t ctx;
834898Skais 
835898Skais 	dd.cd_format = CRYPTO_DATA_RAW;
836898Skais 	dd.cd_offset = 0;
837898Skais 	mac.cd_format = CRYPTO_DATA_RAW;
838898Skais 	mac.cd_offset = 0;
839898Skais 
840898Skais 	/*
841898Skais 	 * A(i) = HMAC_hash(secred, seed + A(i-1));
842898Skais 	 * A(0) = seed;
843898Skais 	 *
844898Skais 	 * Compute A(1):
845898Skais 	 * A(1) = HMAC_hash(secret, label + seed)
846898Skais 	 *
847898Skais 	 */
848898Skais 	HMAC_INIT(mech, key, &ctx);
849898Skais 	HMAC_UPDATE(ctx, label, label_len);
850898Skais 	HMAC_UPDATE(ctx, seed, seedlen);
851898Skais 	HMAC_FINAL(ctx, A1, hashlen);
852898Skais 
853898Skais 	/* Compute A(2) ... A(n) */
854898Skais 	while (bytes_left > 0) {
855898Skais 		HMAC_INIT(mech, key, &ctx);
856898Skais 		HMAC_UPDATE(ctx, A1, hashlen);
857898Skais 		HMAC_UPDATE(ctx, label, label_len);
858898Skais 		HMAC_UPDATE(ctx, seed, seedlen);
859898Skais 		HMAC_FINAL(ctx, result, hashlen);
860898Skais 
861898Skais 		/*
862898Skais 		 * The A(i) value is stored in "result".
863898Skais 		 * Save the results of the MAC so it can be input to next
864898Skais 		 * iteration.
865898Skais 		 */
866898Skais 		if (bytes_left > hashlen) {
867898Skais 			/* Store the chunk result */
868898Skais 			bcopy(result, data, hashlen);
869898Skais 			data += hashlen;
870898Skais 
871898Skais 			bytes_left -= hashlen;
872898Skais 
873898Skais 			/* Update A1 for next iteration */
874898Skais 			HMAC_INIT(mech, key, &ctx);
875898Skais 			HMAC_UPDATE(ctx, A1, hashlen);
876898Skais 			HMAC_FINAL(ctx, A1, hashlen);
877898Skais 
878898Skais 		} else {
879898Skais 			bcopy(result, data, bytes_left);
880898Skais 			data += bytes_left;
881898Skais 			bytes_left = 0;
882898Skais 		}
883898Skais 	}
884898Skais end:
885898Skais 	if (CRYPTO_ERR(rv)) {
886898Skais #ifdef	DEBUG
887898Skais 		cmn_err(CE_WARN, "kssl_P_hash: crypto_mac error 0x%02X", rv);
888898Skais #endif	/* DEBUG */
889898Skais 		KSSL_COUNTER(compute_mac_failure, 1);
890898Skais 	}
891898Skais 	return (rv);
892898Skais }
893898Skais 
894898Skais /* ARGSUSED */
895898Skais static int
896898Skais kssl_tls_PRF(ssl_t *ssl,
897898Skais 	uchar_t *secret, size_t secret_len,
898898Skais 	uchar_t *label, size_t label_len,
899898Skais 	uchar_t *seed, size_t seed_len,
900898Skais 	uchar_t *prfresult, size_t prfresult_len)
901898Skais {
902898Skais 	/*
903898Skais 	 * RFC 2246:
904898Skais 	 *  PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
905898Skais 	 *				P_SHA1(S2, label + seed);
906898Skais 	 * S1 = 1st half of secret.
907898Skais 	 * S1 = 2nd half of secret.
908898Skais 	 *
909898Skais 	 */
910898Skais 
911898Skais 	int rv = 0, i;
912898Skais 	uchar_t psha1[MAX_TLS_KEYBLOCK_SIZE];
913898Skais 	crypto_key_t S1, S2;
914898Skais 
915898Skais 	/* length of secret keys is ceil(length/2) */
916898Skais 	size_t slen = roundup(secret_len, 2) / 2;
917898Skais 
918898Skais 	if (prfresult_len > MAX_TLS_KEYBLOCK_SIZE) {
919898Skais 		KSSL_DEBUG2_IF(kssl_debug, "kssl_tls_PRF: unexpected keyblock "
920898Skais 			"size (%lu)", prfresult_len);
921898Skais 		return (CRYPTO_ARGUMENTS_BAD);
922898Skais 	}
923898Skais 
924898Skais 	ASSERT(prfresult != NULL);
925898Skais 	ASSERT(label != NULL);
926898Skais 	ASSERT(seed != NULL);
927898Skais 
928898Skais 	S1.ck_data   = secret;
929898Skais 	S1.ck_length = slen * 8; /* bits */
930898Skais 	S1.ck_format = CRYPTO_KEY_RAW;
931898Skais 
932898Skais 	S2.ck_data   = secret + slen;
933898Skais 	S2.ck_length = slen * 8; /* bits */
934898Skais 	S2.ck_format = CRYPTO_KEY_RAW;
935898Skais 
936898Skais 	rv = kssl_tls_P_hash(&hmac_md5_mech, &S1, MD5_HASH_LEN,
937898Skais 			label, label_len,
938898Skais 			seed, seed_len,
939898Skais 			prfresult, prfresult_len);
940898Skais 	if (CRYPTO_ERR(rv))
941898Skais 		goto end;
942898Skais 
943898Skais 	rv = kssl_tls_P_hash(&hmac_sha1_mech, &S2, SHA1_HASH_LEN,
944898Skais 			label, label_len,
945898Skais 			seed, seed_len,
946898Skais 			psha1, prfresult_len);
947898Skais 	if (CRYPTO_ERR(rv))
948898Skais 		goto end;
949898Skais 
950898Skais 	for (i = 0; i < prfresult_len; i++)
951898Skais 		prfresult[i] ^= psha1[i];
952898Skais 
953898Skais end:
954898Skais 	if (CRYPTO_ERR(rv))
955898Skais 		bzero(prfresult, prfresult_len);
956898Skais 
957898Skais 	return (rv);
958898Skais }
959898Skais 
9601724Skrishna #define	IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)			\
9611724Skrishna 	(pms == NULL || pmslen != SSL3_PRE_MASTER_SECRET_LEN ||		\
9621724Skrishna 	pms[0] != ssl->major_version || pms[1] != ssl->minor_version)
9631724Skrishna 
9641724Skrishna #define	FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf) {			\
9651724Skrishna 		KSSL_COUNTER(bad_pre_master_secret, 1);			\
9661724Skrishna 		pms = buf;						\
9671724Skrishna 		pmslen = SSL3_PRE_MASTER_SECRET_LEN;			\
9681724Skrishna 		pms[0] = ssl->major_version;				\
9691724Skrishna 		pms[1] = ssl->minor_version;				\
9701724Skrishna 		(void) random_get_pseudo_bytes(&buf[2], pmslen - 2);	\
9711724Skrishna }
9721724Skrishna 
973898Skais static int
974898Skais kssl_generate_tls_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen)
975898Skais {
9761724Skrishna 	uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN];
977898Skais 	uchar_t seed[SSL3_RANDOM_LENGTH * 2];
978898Skais 
979898Skais 	/*
980898Skais 	 * Computing the master secret:
981898Skais 	 * ----------------------------
982898Skais 	 * master_secret = PRF (pms, "master secret",
983898Skais 	 *		ClientHello.random + ServerHello.random);
984898Skais 	 */
985898Skais 	bcopy(ssl->client_random, seed, SSL3_RANDOM_LENGTH);
986898Skais 	bcopy(ssl->server_random, seed + SSL3_RANDOM_LENGTH,
987898Skais 		SSL3_RANDOM_LENGTH);
988898Skais 
9891724Skrishna 	/* if pms is bad fake it to thwart Bleichenbacher attack */
9901724Skrishna 	if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) {
9911724Skrishna #ifdef	DEBUG
9921724Skrishna 		cmn_err(CE_WARN, "Under Bleichenbacher attack");
9931724Skrishna #endif	/* DEBUG */
9941724Skrishna 		FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf);
9951724Skrishna 	}
9961724Skrishna 
997898Skais 	return (kssl_tls_PRF(ssl,
998898Skais 		pms, pmslen,
999898Skais 		(uchar_t *)TLS_MASTER_SECRET_LABEL,
1000898Skais 		(size_t)strlen(TLS_MASTER_SECRET_LABEL),
1001898Skais 		seed, sizeof (seed),
1002898Skais 		ssl->sid.master_secret,
1003898Skais 		(size_t)sizeof (ssl->sid.master_secret)));
1004898Skais }
1005898Skais 
10061724Skrishna 
1007898Skais static void
1008898Skais kssl_generate_ssl_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen)
1009898Skais {
1010898Skais 	uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN];
1011898Skais 	uchar_t *ms;
1012898Skais 	int hlen = MD5_HASH_LEN;
1013898Skais 
1014898Skais 	ms = ssl->sid.master_secret;
1015898Skais 
1016898Skais 	/* if pms is bad fake it to thwart Bleichenbacher attack */
10171724Skrishna 	if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) {
1018898Skais #ifdef	DEBUG
1019898Skais 		cmn_err(CE_WARN, "Under Bleichenbacher attack");
1020898Skais #endif	/* DEBUG */
10211724Skrishna 		FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf);
1022898Skais 	}
10231724Skrishna 
1024898Skais 	kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 1, ms, 0);
1025898Skais 	kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 2, ms + hlen, 0);
1026898Skais 	kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 3, ms + 2 * hlen,
1027898Skais 	    0);
1028898Skais }
1029898Skais 
1030898Skais static int
1031898Skais kssl_generate_tls_keyblock(ssl_t *ssl)
1032898Skais {
1033898Skais 	uchar_t seed[2 * SSL3_RANDOM_LENGTH];
1034898Skais 
1035898Skais 	bcopy(ssl->server_random, seed, SSL3_RANDOM_LENGTH);
1036898Skais 	bcopy(ssl->client_random, seed + SSL3_RANDOM_LENGTH,
1037898Skais 		SSL3_RANDOM_LENGTH);
1038898Skais 
1039898Skais 	return (kssl_tls_PRF(ssl, ssl->sid.master_secret,
1040898Skais 		(size_t)SSL3_MASTER_SECRET_LEN,
1041898Skais 		(uchar_t *)TLS_KEY_EXPANSION_LABEL,
1042898Skais 		(size_t)strlen(TLS_KEY_EXPANSION_LABEL),
1043898Skais 		seed, (size_t)sizeof (seed),
1044898Skais 		ssl->pending_keyblock,
1045898Skais 		(size_t)ssl->pending_keyblksz));
1046898Skais 
1047898Skais }
1048898Skais 
1049898Skais static void
1050898Skais kssl_generate_keyblock(ssl_t *ssl)
1051898Skais {
1052898Skais 	uchar_t *ms;
1053898Skais 	size_t mslen = SSL3_MASTER_SECRET_LEN;
1054898Skais 	int hlen = MD5_HASH_LEN;
1055898Skais 	uchar_t *keys = ssl->pending_keyblock;
1056898Skais 	int steps = howmany(ssl->pending_keyblksz, hlen);
1057898Skais 	int i;
1058898Skais 
1059898Skais 	ms = ssl->sid.master_secret;
1060898Skais 
1061898Skais 	ASSERT(hlen * steps <= MAX_KEYBLOCK_LENGTH);
1062898Skais 
1063898Skais 	for (i = 1; i <= steps; i++) {
1064898Skais 		kssl_ssl3_key_material_derive_step(ssl, ms, mslen, i, keys, 1);
1065898Skais 		keys += hlen;
1066898Skais 	}
1067898Skais }
1068898Skais 
1069898Skais static char *ssl3_key_derive_seeds[8] = {"A", "BB", "CCC", "DDDD", "EEEEE",
1070898Skais 					    "FFFFFF", "GGGGGGG", "HHHHHHHH"};
1071898Skais 
1072898Skais static void
1073898Skais kssl_ssl3_key_material_derive_step(
1074898Skais 	ssl_t *ssl,
1075898Skais 	uchar_t *secret,
1076898Skais 	size_t secretlen,
1077898Skais 	int step,
1078898Skais 	uchar_t *dst,
1079898Skais 	int sr_first)
1080898Skais {
1081898Skais 	SHA1_CTX sha1, *sha1ctx;
1082898Skais 	MD5_CTX md5, *md5ctx;
1083898Skais 	uchar_t sha1_hash[SHA1_HASH_LEN];
1084898Skais 
1085898Skais 	sha1ctx = &sha1;
1086898Skais 	md5ctx = &md5;
1087898Skais 
1088898Skais 	ASSERT(step <=
1089898Skais 	    sizeof (ssl3_key_derive_seeds) /
1090898Skais 	    sizeof (ssl3_key_derive_seeds[0]));
1091898Skais 	step--;
1092898Skais 
1093898Skais 	SHA1Init(sha1ctx);
1094898Skais 	SHA1Update(sha1ctx, (uchar_t *)ssl3_key_derive_seeds[step],
1095898Skais 	    step + 1);
1096898Skais 	SHA1Update(sha1ctx, secret, secretlen);
1097898Skais 	if (sr_first) {
1098898Skais 		SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH);
1099898Skais 		SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH);
1100898Skais 	} else {
1101898Skais 		SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH);
1102898Skais 		SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH);
1103898Skais 	}
1104898Skais 	SHA1Final(sha1_hash, sha1ctx);
1105898Skais 
1106898Skais 	MD5Init(md5ctx);
1107898Skais 	MD5Update(md5ctx, secret, secretlen);
1108898Skais 	MD5Update(md5ctx, sha1_hash, SHA1_HASH_LEN);
1109898Skais 	MD5Final(dst, md5ctx);
1110898Skais }
1111898Skais 
1112898Skais static int
1113898Skais kssl_send_certificate_and_server_hello_done(ssl_t *ssl)
1114898Skais {
1115898Skais 	int cur_reclen;
1116898Skais 	int mss;
1117898Skais 	int len, copylen;
1118898Skais 	mblk_t *mp;
1119898Skais 	uchar_t *cert_buf;
1120898Skais 	int cert_len;
1121898Skais 	uchar_t *msgbuf;
1122898Skais 	Certificate_t *cert;
1123898Skais 
1124898Skais 	cert = ssl->kssl_entry->ke_server_certificate;
1125898Skais 	if (cert == NULL) {
1126898Skais 	    return (ENOENT);
1127898Skais 	}
1128898Skais 	cert_buf = cert->msg;
1129898Skais 	cert_len = cert->len;
1130898Skais 
1131898Skais 	mp = ssl->handshake_sendbuf;
1132898Skais 	mss = ssl->tcp_mss;
1133898Skais 	ASSERT(mp != NULL);
1134898Skais 	cur_reclen = mp->b_wptr - mp->b_rptr - SSL3_HDR_LEN;
1135898Skais 	ASSERT(cur_reclen == KSSL_SSL3_SH_RECLEN);
1136898Skais 	/* Assume MSS is at least 80 bytes */
1137898Skais 	ASSERT(mss > cur_reclen + SSL3_HDR_LEN);
1138898Skais 	ASSERT(cur_reclen < SSL3_MAX_RECORD_LENGTH); /* XXX */
1139898Skais 
1140898Skais 	copylen = mss - (cur_reclen + SSL3_HDR_LEN);
1141898Skais 	len = cert_len;
1142898Skais 	copylen = MIN(copylen, len);
1143898Skais 	copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen);
1144898Skais 
1145898Skais 	/* new record always starts in a new mblk for simplicity */
1146898Skais 	msgbuf = cert_buf;
1147898Skais 	for (;;) {
1148898Skais 		ASSERT(mp->b_wptr + copylen <= mp->b_datap->db_lim);
1149898Skais 		bcopy(msgbuf, mp->b_wptr, copylen);
1150898Skais 		msgbuf += copylen;
1151898Skais 		mp->b_wptr += copylen;
1152898Skais 		cur_reclen += copylen;
1153898Skais 		len -= copylen;
1154898Skais 		if (len == 0) {
1155898Skais 			break;
1156898Skais 		}
1157898Skais 		if (cur_reclen == SSL3_MAX_RECORD_LENGTH) {
1158898Skais 			cur_reclen = 0;
1159898Skais 		}
1160898Skais 		copylen = MIN(len, mss);
1161898Skais 		copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen);
1162898Skais 		mp->b_cont = allocb(copylen, BPRI_HI);
1163898Skais 		if (mp->b_cont == NULL) {
1164898Skais 			KSSL_COUNTER(alloc_fails, 1);
1165898Skais 			freemsg(ssl->handshake_sendbuf);
1166898Skais 			ssl->handshake_sendbuf = NULL;
1167898Skais 			return (ENOMEM);
1168898Skais 		}
1169898Skais 		mp = mp->b_cont;
1170898Skais 		if (cur_reclen == 0) {
1171898Skais 			mp->b_wptr[0] = content_handshake;
1172898Skais 			mp->b_wptr[1] = ssl->major_version;
1173898Skais 			mp->b_wptr[2] = ssl->minor_version;
1174898Skais 			cur_reclen = MIN(len, SSL3_MAX_RECORD_LENGTH);
1175898Skais 			mp->b_wptr[3] = (cur_reclen >> 8) & 0xff;
1176898Skais 			mp->b_wptr[4] = (cur_reclen) & 0xff;
1177898Skais 			mp->b_wptr += SSL3_HDR_LEN;
1178898Skais 			cur_reclen = 0;
1179898Skais 			copylen = MIN(copylen, mss - SSL3_HDR_LEN);
1180898Skais 		}
1181898Skais 	}
1182898Skais 
1183898Skais 	/* adjust the record length field for the first record */
1184898Skais 	mp = ssl->handshake_sendbuf;
1185898Skais 	cur_reclen = MIN(KSSL_SSL3_SH_RECLEN + cert_len,
1186898Skais 	    SSL3_MAX_RECORD_LENGTH);
1187898Skais 	mp->b_rptr[3] = (cur_reclen >> 8) & 0xff;
1188898Skais 	mp->b_rptr[4] = (cur_reclen) & 0xff;
1189898Skais 
1190898Skais 	kssl_update_handshake_hashes(ssl, cert_buf, cert_len);
1191898Skais 
1192898Skais 	return (0);
1193898Skais }
1194898Skais 
1195898Skais static int
1196898Skais kssl_send_change_cipher_specs(ssl_t *ssl)
1197898Skais {
1198898Skais 	mblk_t *mp, *newmp;
1199898Skais 	uchar_t *buf;
1200898Skais 
1201898Skais 	mp = ssl->handshake_sendbuf;
1202898Skais 
1203898Skais 	/* We're most likely to hit the fast path for resumed sessions */
1204898Skais 	if ((mp != NULL) &&
1205898Skais 	    (mp->b_datap->db_lim - mp->b_wptr > KSSL_SSL3_MAX_CCP_FIN_MSGLEN)) {
1206898Skais 		buf = mp->b_wptr;
1207898Skais 	} else {
1208898Skais 		newmp = allocb(KSSL_SSL3_MAX_CCP_FIN_MSGLEN, BPRI_HI);
1209898Skais 
1210898Skais 		if (newmp == NULL)
1211898Skais 			return (ENOMEM);	/* need to do better job! */
1212898Skais 
1213898Skais 		if (mp == NULL) {
1214898Skais 			ssl->handshake_sendbuf = newmp;
1215898Skais 		} else {
1216898Skais 			linkb(ssl->handshake_sendbuf, newmp);
1217898Skais 		}
1218898Skais 		mp = newmp;
1219898Skais 		buf = mp->b_rptr;
1220898Skais 	}
1221898Skais 
1222898Skais 	/* 5 byte record header */
1223898Skais 	buf[0] = content_change_cipher_spec;
1224898Skais 	buf[1] = ssl->major_version;
1225898Skais 	buf[2] = ssl->minor_version;
1226898Skais 	buf[3] = 0;
1227898Skais 	buf[4] = 1;
1228898Skais 	buf += SSL3_HDR_LEN;
1229898Skais 
1230898Skais 	buf[0] = 1;
1231898Skais 
1232898Skais 	mp->b_wptr = buf + 1;
1233898Skais 	ASSERT(mp->b_wptr < mp->b_datap->db_lim);
1234898Skais 
1235898Skais 	ssl->seq_num[KSSL_WRITE] = 0;
1236898Skais 	return (kssl_spec_init(ssl, KSSL_WRITE));
1237898Skais }
1238898Skais 
1239898Skais int
1240898Skais kssl_spec_init(ssl_t *ssl, int dir)
1241898Skais {
1242898Skais 	KSSL_HASHCTX *ctx;
1243898Skais 	KSSLCipherSpec *spec = &ssl->spec[dir];
1244898Skais 	int ret = 0;
1245898Skais 
1246898Skais 	spec->mac_hashsz = mac_defs[ssl->pending_malg].hashsz;
1247898Skais 	spec->mac_padsz = mac_defs[ssl->pending_malg].padsz;
1248898Skais 
1249898Skais 	spec->MAC_HashInit = mac_defs[ssl->pending_malg].HashInit;
1250898Skais 	spec->MAC_HashUpdate = mac_defs[ssl->pending_malg].HashUpdate;
1251898Skais 	spec->MAC_HashFinal = mac_defs[ssl->pending_malg].HashFinal;
1252898Skais 
1253898Skais 	if (dir == KSSL_READ) {
1254898Skais 		bcopy(ssl->pending_keyblock, ssl->mac_secret[dir],
1255898Skais 		    spec->mac_hashsz);
1256898Skais 	} else {
1257898Skais 		bcopy(&(ssl->pending_keyblock[spec->mac_hashsz]),
1258898Skais 		    ssl->mac_secret[dir], spec->mac_hashsz);
1259898Skais 	}
1260898Skais 
1261898Skais 	/* Pre-compute these here. will save cycles on each record later */
1262898Skais 	if (!IS_TLS(ssl)) {
1263898Skais 		ctx = &ssl->mac_ctx[dir][0];
1264898Skais 		spec->MAC_HashInit((void *)ctx);
1265898Skais 		spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir],
1266898Skais 		    spec->mac_hashsz);
1267898Skais 		spec->MAC_HashUpdate((void *)ctx, kssl_pad_1,
1268898Skais 			spec->mac_padsz);
1269898Skais 
1270898Skais 		ctx = &ssl->mac_ctx[dir][1];
1271898Skais 		spec->MAC_HashInit((void *)ctx);
1272898Skais 		spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir],
1273898Skais 		    spec->mac_hashsz);
1274898Skais 		spec->MAC_HashUpdate((void *)ctx, kssl_pad_2,
1275898Skais 			spec->mac_padsz);
1276898Skais 	}
1277898Skais 
1278898Skais 	spec->cipher_type = cipher_defs[ssl->pending_calg].type;
1279898Skais 	spec->cipher_mech.cm_type = cipher_defs[ssl->pending_calg].mech_type;
1280898Skais 	spec->cipher_bsize = cipher_defs[ssl->pending_calg].bsize;
1281898Skais 	spec->cipher_keysz = cipher_defs[ssl->pending_calg].keysz;
1282898Skais 
1283898Skais 	if (spec->cipher_ctx != NULL) {
1284898Skais 		crypto_cancel_ctx(spec->cipher_ctx);
1285898Skais 		spec->cipher_ctx = 0;
1286898Skais 	}
1287898Skais 
1288898Skais 	/*
1289*4859Skrishna 	 * Initialize HMAC keys for TLS and SSL3 HMAC keys
1290*4859Skrishna 	 * for SSL 3.0.
1291898Skais 	 */
1292898Skais 	if (IS_TLS(ssl)) {
1293898Skais 		if (ssl->pending_malg == mac_md5) {
1294898Skais 			spec->hmac_mech = hmac_md5_mech;
1295898Skais 		} else if (ssl->pending_malg == mac_sha) {
1296898Skais 			spec->hmac_mech = hmac_sha1_mech;
1297898Skais 		}
1298898Skais 
1299898Skais 		spec->hmac_key.ck_format = CRYPTO_KEY_RAW;
1300898Skais 		spec->hmac_key.ck_data = ssl->mac_secret[dir];
1301898Skais 		spec->hmac_key.ck_length = spec->mac_hashsz * 8;
1302*4859Skrishna 	} else {
1303*4859Skrishna 		static uint32_t param;
1304*4859Skrishna 
1305*4859Skrishna 		spec->hmac_mech.cm_type = CRYPTO_MECH_INVALID;
1306*4859Skrishna 		spec->hmac_mech.cm_param = (caddr_t)&param;
1307*4859Skrishna 		spec->hmac_mech.cm_param_len = sizeof (param);
1308*4859Skrishna 		if (ssl->pending_malg == mac_md5) {
1309*4859Skrishna 			spec->hmac_mech.cm_type =
1310*4859Skrishna 			    crypto_mech2id("CKM_SSL3_MD5_MAC");
1311*4859Skrishna 			param = MD5_HASH_LEN;
1312*4859Skrishna 		} else if (ssl->pending_malg == mac_sha) {
1313*4859Skrishna 			spec->hmac_mech.cm_type =
1314*4859Skrishna 			    crypto_mech2id("CKM_SSL3_SHA1_MAC");
1315*4859Skrishna 			param = SHA1_HASH_LEN;
1316*4859Skrishna 		}
1317*4859Skrishna 
1318*4859Skrishna 		spec->hmac_key.ck_format = CRYPTO_KEY_RAW;
1319*4859Skrishna 		spec->hmac_key.ck_data = ssl->mac_secret[dir];
1320*4859Skrishna 		spec->hmac_key.ck_length = spec->mac_hashsz * 8;
1321898Skais 	}
1322898Skais 
1323898Skais 	/* We're done if this is the nil cipher */
1324898Skais 	if (spec->cipher_keysz == 0) {
1325898Skais 		return (0);
1326898Skais 	}
1327898Skais 
1328898Skais 	/* Initialize the key and the active context */
1329898Skais 	spec->cipher_key.ck_format = CRYPTO_KEY_RAW;
1330898Skais 	spec->cipher_key.ck_length = 8 * spec->cipher_keysz; /* in bits */
1331898Skais 
1332898Skais 	if (cipher_defs[ssl->pending_calg].bsize > 0) {
1333898Skais 		/* client_write_IV */
1334898Skais 		spec->cipher_mech.cm_param =
1335898Skais 		    (caddr_t)&(ssl->pending_keyblock[2 * spec->mac_hashsz +
1336898Skais 		    2 * spec->cipher_keysz]);
1337898Skais 		spec->cipher_mech.cm_param_len = spec->cipher_bsize;
1338898Skais 	}
1339898Skais 	spec->cipher_data.cd_format = CRYPTO_DATA_RAW;
1340898Skais 	if (dir == KSSL_READ) {
1341898Skais 		spec->cipher_mech.cm_param_len =
1342898Skais 		    cipher_defs[ssl->pending_calg].bsize;
1343898Skais 
13442800Skrishna 		/* client_write_key */
1345898Skais 		spec->cipher_key.ck_data =
1346898Skais 		    &(ssl->pending_keyblock[2 * spec->mac_hashsz]);
1347898Skais 
1348898Skais 		ret = crypto_decrypt_init(&(spec->cipher_mech),
1349898Skais 			&(spec->cipher_key), NULL, &spec->cipher_ctx, NULL);
1350898Skais #ifdef	DEBUG
1351898Skais 		if (CRYPTO_ERR(ret)) {
1352898Skais 			cmn_err(CE_WARN, "kssl_spec_init: "
1353898Skais 				"crypto_decrypt_init error 0x%02X", ret);
1354898Skais 		}
1355898Skais #endif	/* DEBUG */
1356898Skais 	} else {
1357898Skais 		if (cipher_defs[ssl->pending_calg].bsize > 0) {
1358898Skais 			spec->cipher_mech.cm_param += spec->cipher_bsize;
1359898Skais 		}
1360898Skais 		/* server_write_key */
1361898Skais 		spec->cipher_key.ck_data =
1362898Skais 		    &(ssl->pending_keyblock[2 * spec->mac_hashsz +
1363898Skais 		    spec->cipher_keysz]);
1364898Skais 
1365898Skais 		ret = crypto_encrypt_init(&(spec->cipher_mech),
1366898Skais 			&(spec->cipher_key), NULL, &spec->cipher_ctx, NULL);
1367898Skais #ifdef	DEBUG
1368898Skais 		if (CRYPTO_ERR(ret))
1369898Skais 			cmn_err(CE_WARN, "kssl_spec_init: "
1370898Skais 				"crypto_encrypt_init error 0x%02X", ret);
1371898Skais #endif	/* DEBUG */
1372898Skais 	}
1373898Skais 	return (ret);
1374898Skais }
1375898Skais 
1376898Skais static int
1377898Skais kssl_send_finished(ssl_t *ssl, int update_hsh)
1378898Skais {
1379898Skais 	mblk_t *mp;
1380898Skais 	uchar_t *buf;
1381898Skais 	uchar_t *rstart;
1382898Skais 	uchar_t *versionp;
1383898Skais 	SSL3Hashes ssl3hashes;
1384898Skais 	size_t finish_len;
1385898Skais 	int ret = 0;
1386898Skais 
1387898Skais 	mp = ssl->handshake_sendbuf;
1388898Skais 	ASSERT(mp != NULL);
1389898Skais 	buf = mp->b_wptr;
1390898Skais 	ASSERT(buf - mp->b_rptr == SSL3_HDR_LEN + KSSL_SSL3_SH_RECLEN +
1391898Skais 	    SSL3_HDR_LEN + 1 || buf - mp->b_rptr == SSL3_HDR_LEN + 1);
1392898Skais 
1393898Skais 	rstart = buf;
1394898Skais 
1395898Skais 	if (IS_TLS(ssl))
1396898Skais 		finish_len = TLS_FINISHED_SIZE;
1397898Skais 	else
1398898Skais 		finish_len = KSSL_SSL3_FIN_MSGLEN;
1399898Skais 
1400898Skais 	/* 5 byte record header */
1401898Skais 	buf[0] = content_handshake;
1402898Skais 	buf[1] = ssl->major_version;
1403898Skais 	buf[2] = ssl->minor_version;
1404898Skais 	buf[3] = 0;
1405898Skais 	buf[4] = 4 + finish_len;
1406898Skais 
1407898Skais 	versionp = &buf[1];
1408898Skais 
1409898Skais 	buf += SSL3_HDR_LEN;
1410898Skais 
1411898Skais 	/* 4 byte message header */
1412898Skais 	buf[0] = (uchar_t)finished;	/* message type */
1413898Skais 	buf[1] = 0;			/* message len byte 0 */
1414898Skais 	buf[2] = 0;			/* message len byte 1 */
1415898Skais 	buf[3] = finish_len;	/* message len byte 2 */
1416898Skais 	buf += 4;
1417898Skais 
1418898Skais 	if (IS_TLS(ssl)) {
1419898Skais 		bcopy(ssl->hs_hashes.md5, ssl3hashes.md5,
1420898Skais 			sizeof (ssl3hashes.md5));
1421898Skais 		bcopy(ssl->hs_hashes.sha1, ssl3hashes.sha1,
1422898Skais 			sizeof (ssl3hashes.sha1));
1423898Skais 	}
1424898Skais 
1425898Skais 	/* Compute hashes for the SENDER side */
1426898Skais 	ret = kssl_compute_handshake_hashes(ssl, &ssl3hashes, sender_server);
1427898Skais 	if (ret != 0)
1428898Skais 		return (ret);
1429898Skais 
1430898Skais 	if (IS_TLS(ssl)) {
1431898Skais 		bcopy(ssl3hashes.tlshash, buf, sizeof (ssl3hashes.tlshash));
1432898Skais 	} else {
1433898Skais 		bcopy(ssl3hashes.md5, buf, MD5_HASH_LEN);
1434898Skais 		bcopy(ssl3hashes.sha1, buf + MD5_HASH_LEN, SHA1_HASH_LEN);
1435898Skais 	}
1436898Skais 
1437898Skais 	if (update_hsh) {
1438898Skais 		kssl_update_handshake_hashes(ssl, buf - 4, finish_len + 4);
1439898Skais 	}
1440898Skais 
1441898Skais 	mp->b_wptr = buf + finish_len;
1442898Skais 
1443898Skais 	ret = kssl_mac_encrypt_record(ssl, content_handshake, versionp,
1444898Skais 	    rstart, mp);
1445898Skais 	ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
1446898Skais 
1447898Skais 	return (ret);
1448898Skais }
1449898Skais 
1450898Skais int
1451898Skais kssl_mac_encrypt_record(ssl_t *ssl,
1452898Skais 	SSL3ContentType ct,
1453898Skais 	uchar_t *versionp,
1454898Skais 	uchar_t *rstart,
1455898Skais 	mblk_t *mp)
1456898Skais {
1457898Skais 	KSSLCipherSpec *spec;
1458898Skais 	int mac_sz;
1459898Skais 	int ret = 0;
1460898Skais 	uint16_t rec_sz;
1461898Skais 	int pad_sz;
1462898Skais 	int i;
1463898Skais 
1464898Skais 	ASSERT(ssl != NULL);
1465898Skais 	ASSERT(rstart >= mp->b_rptr);
1466898Skais 	ASSERT(rstart < mp->b_wptr);
1467898Skais 
1468898Skais 	spec = &ssl->spec[KSSL_WRITE];
1469898Skais 	mac_sz = spec->mac_hashsz;
1470898Skais 
1471898Skais 	rec_sz = (mp->b_wptr - rstart) - SSL3_HDR_LEN;
1472898Skais 	ASSERT(rec_sz > 0);
1473898Skais 
1474898Skais 	if (mac_sz != 0) {
1475898Skais 		ASSERT(mp->b_wptr + mac_sz <= mp->b_datap->db_lim);
1476898Skais 		ret = kssl_compute_record_mac(ssl, KSSL_WRITE,
1477898Skais 		    ssl->seq_num[KSSL_WRITE], ct, versionp,
1478898Skais 		    rstart + SSL3_HDR_LEN, rec_sz, mp->b_wptr);
1479898Skais 		if (ret == CRYPTO_SUCCESS) {
1480898Skais 			ssl->seq_num[KSSL_WRITE]++;
1481898Skais 			mp->b_wptr += mac_sz;
1482898Skais 			rec_sz += mac_sz;
1483898Skais 		} else {
1484898Skais 			return (ret);
1485898Skais 		}
1486898Skais 	}
1487898Skais 
1488898Skais 	if (spec->cipher_type == type_block) {
1489898Skais 		pad_sz = spec->cipher_bsize -
1490898Skais 		    (rec_sz & (spec->cipher_bsize - 1));
1491898Skais 		ASSERT(mp->b_wptr + pad_sz <= mp->b_datap->db_lim);
1492898Skais 		for (i = 0; i < pad_sz; i++) {
1493898Skais 			mp->b_wptr[i] = pad_sz - 1;
1494898Skais 		}
1495898Skais 		mp->b_wptr += pad_sz;
1496898Skais 		rec_sz += pad_sz;
1497898Skais 	}
1498898Skais 
1499898Skais 	ASSERT(rec_sz <= SSL3_MAX_RECORD_LENGTH);
1500898Skais 
1501898Skais 	U16_TO_BE16(rec_sz, rstart + 3);
1502898Skais 
1503898Skais 	if (spec->cipher_ctx == 0)
1504898Skais 		return (ret);
1505898Skais 
1506898Skais 	spec->cipher_data.cd_length = rec_sz;
1507898Skais 	spec->cipher_data.cd_raw.iov_base = (char *)(rstart + SSL3_HDR_LEN);
1508898Skais 	spec->cipher_data.cd_raw.iov_len = rec_sz;
1509898Skais 	/* One record at a time. Otherwise, gotta allocate the crypt_data_t */
1510898Skais 	ret = crypto_encrypt_update(spec->cipher_ctx, &spec->cipher_data,
1511898Skais 	    NULL, NULL);
1512898Skais #ifdef	DEBUG
1513898Skais 	if (CRYPTO_ERR(ret)) {
1514898Skais 		cmn_err(CE_WARN,
1515898Skais 			"kssl_mac_encrypt_record: crypto_encrypt_update "
1516898Skais 			"error 0x%02X", ret);
1517898Skais 	}
1518898Skais #endif	/* DEBUG */
1519898Skais 	return (ret);
1520898Skais }
1521898Skais 
1522898Skais void
1523898Skais kssl_send_alert(ssl_t *ssl, SSL3AlertLevel level, SSL3AlertDescription desc)
1524898Skais {
1525898Skais 	mblk_t *mp;
1526898Skais 	uchar_t *buf;
1527898Skais 	KSSLCipherSpec *spec;
1528898Skais 
1529898Skais 	ASSERT(ssl != NULL);
1530898Skais 
1531898Skais 	ssl->sendalert_level = level;
1532898Skais 	ssl->sendalert_desc = desc;
1533898Skais 
1534898Skais 	if (level == alert_fatal) {
1535898Skais #ifdef	DEBUG
1536898Skais 		cmn_err(CE_WARN, "sending an alert %d %d from %p\n", level,
1537898Skais 		    desc, (void *)caller());
1538898Skais #endif	/* DEBUG */
1539898Skais 		if (ssl->sid.cached == B_TRUE) {
1540898Skais 			kssl_uncache_sid(&ssl->sid, ssl->kssl_entry);
1541898Skais 			ssl->sid.cached = B_FALSE;
1542898Skais 		}
1543898Skais 		ssl->fatal_alert = B_TRUE;
1544898Skais 		KSSL_COUNTER(fatal_alerts, 1);
1545898Skais 	} else
1546898Skais 		KSSL_COUNTER(warning_alerts, 1);
1547898Skais 
1548898Skais 	spec = &ssl->spec[KSSL_WRITE];
1549898Skais 
1550898Skais 	ASSERT(ssl->alert_sendbuf == NULL);
1551898Skais 	ssl->alert_sendbuf = mp = allocb(7 + spec->mac_hashsz +
1552898Skais 	    spec->cipher_bsize, BPRI_HI);
1553898Skais 	if (mp == NULL) {
1554898Skais 		KSSL_COUNTER(alloc_fails, 1);
1555898Skais 		return;
1556898Skais 	}
1557898Skais 	buf = mp->b_wptr;
1558898Skais 
1559898Skais 	/* 5 byte record header */
1560898Skais 	buf[0] = content_alert;
1561898Skais 	buf[1] = ssl->major_version;
1562898Skais 	buf[2] = ssl->minor_version;
1563898Skais 	buf[3] = 0;
1564898Skais 	buf[4] = 2;
1565898Skais 	buf += SSL3_HDR_LEN;
1566898Skais 
1567898Skais 	/* alert contents */
1568898Skais 	buf[0] = (uchar_t)level;
1569898Skais 	buf[1] = (uchar_t)desc;
1570898Skais 
1571898Skais 	mp->b_wptr = buf + 2;
1572898Skais }
1573898Skais 
1574898Skais /* Assumes RSA encryption */
1575898Skais static int
1576898Skais kssl_handle_client_key_exchange(ssl_t *ssl, mblk_t *mp, int msglen,
1577898Skais     kssl_callback_t cbfn, void *arg)
1578898Skais {
1579898Skais 	char *buf;
1580898Skais 	uchar_t *pms;
1581898Skais 	size_t pmslen;
1582898Skais 	int allocated;
15832800Skrishna 	int err, rverr = ENOMEM;
15842800Skrishna 	kssl_entry_t *ep;
1585898Skais 	crypto_key_t *privkey;
1586898Skais 	crypto_data_t *wrapped_pms_data, *pms_data;
1587898Skais 	crypto_call_req_t creq, *creqp;
1588898Skais 
15892800Skrishna 	ep = ssl->kssl_entry;
15902800Skrishna 	privkey = ep->ke_private_key;
1591898Skais 	if (privkey == NULL) {
15922800Skrishna 		return (ENOENT);
1593898Skais 	}
1594898Skais 
1595898Skais 	ASSERT(ssl->msg.type == client_key_exchange);
1596898Skais 	ASSERT(ssl->hs_waitstate == wait_client_key);
1597898Skais 
1598898Skais 	/*
1599898Skais 	 * TLS adds an extra 2 byte length field before the data.
1600898Skais 	 */
1601898Skais 	if (IS_TLS(ssl)) {
1602898Skais 		msglen = (mp->b_rptr[0] << 8) | mp->b_rptr[1];
1603898Skais 		mp->b_rptr += 2;
1604898Skais 	}
1605898Skais 
1606898Skais 	/*
1607898Skais 	 * Allocate all we need in one shot. about 300 bytes total, for
1608898Skais 	 * 1024 bit RSA modulus.
1609898Skais 	 * The buffer layout will be: pms_data, wrapped_pms_data, the
1610898Skais 	 * value of the wrapped pms from the client, then room for the
1611898Skais 	 * resulting decrypted premaster secret.
1612898Skais 	 */
1613898Skais 	allocated = 2 * (sizeof (crypto_data_t) + msglen);
1614898Skais 	buf = kmem_alloc(allocated, KM_NOSLEEP);
1615898Skais 	if (buf == NULL) {
1616898Skais 		return (ENOMEM);
1617898Skais 	}
1618898Skais 
1619898Skais 	pms_data = (crypto_data_t *)buf;
1620898Skais 	wrapped_pms_data = &(((crypto_data_t *)buf)[1]);
1621898Skais 
1622898Skais 	wrapped_pms_data->cd_format = pms_data->cd_format = CRYPTO_DATA_RAW;
1623898Skais 	wrapped_pms_data->cd_offset = pms_data->cd_offset = 0;
1624898Skais 	wrapped_pms_data->cd_length = pms_data->cd_length = msglen;
1625898Skais 	wrapped_pms_data->cd_miscdata = pms_data->cd_miscdata = NULL;
1626898Skais 	wrapped_pms_data->cd_raw.iov_len = pms_data->cd_raw.iov_len = msglen;
1627898Skais 	wrapped_pms_data->cd_raw.iov_base = buf + 2 * sizeof (crypto_data_t);
1628898Skais 	pms_data->cd_raw.iov_base = wrapped_pms_data->cd_raw.iov_base + msglen;
1629898Skais 
1630898Skais 	bcopy(mp->b_rptr, wrapped_pms_data->cd_raw.iov_base, msglen);
1631898Skais 	mp->b_rptr += msglen;
1632898Skais 
1633898Skais 	/* Proceed synchronously if out of interrupt and configured to do so */
1634898Skais 	if ((kssl_synchronous) && (!servicing_interrupt())) {
1635898Skais 		creqp = NULL;
1636898Skais 	} else {
1637898Skais 		ssl->cke_callback_func = cbfn;
1638898Skais 		ssl->cke_callback_arg = arg;
1639898Skais 		creq.cr_flag = kssl_call_flag;
1640898Skais 		creq.cr_callback_func = kssl_cke_done;
1641898Skais 		creq.cr_callback_arg = ssl;
1642898Skais 
1643898Skais 		/* The callback routine will release this one */
1644898Skais 		KSSL_SSL_REFHOLD(ssl);
1645898Skais 
1646898Skais 		creqp = &creq;
1647898Skais 	}
1648898Skais 
16492800Skrishna 	if (ep->ke_is_nxkey) {
16502800Skrishna 		kssl_session_info_t *s;
16512800Skrishna 
16522800Skrishna 		s = ep->ke_sessinfo;
16532800Skrishna 		err = CRYPTO_SUCCESS;
16542800Skrishna 		if (!s->is_valid_handle) {
16552800Skrishna 			/* Reauthenticate to the provider */
16562800Skrishna 			if (s->do_reauth) {
16572800Skrishna 				err = kssl_get_obj_handle(ep);
16582800Skrishna 				if (err == CRYPTO_SUCCESS) {
16592800Skrishna 					s->is_valid_handle = B_TRUE;
16602800Skrishna 					s->do_reauth = B_FALSE;
16612800Skrishna 				}
16622800Skrishna 			} else
16632800Skrishna 				err = CRYPTO_FAILED;
16642800Skrishna 		}
16652800Skrishna 
16662800Skrishna 		if (err == CRYPTO_SUCCESS) {
16672800Skrishna 			ASSERT(s->is_valid_handle);
16682800Skrishna 			err = crypto_decrypt_prov(s->prov, s->sid,
16692800Skrishna 			    &rsa_x509_mech, wrapped_pms_data, &s->key,
16702800Skrishna 			    NULL, pms_data, creqp);
16712800Skrishna 		}
16722800Skrishna 
16732800Skrishna 		/*
16742800Skrishna 		 * Deal with session specific errors. We translate to
16752800Skrishna 		 * the closest errno.
16762800Skrishna 		 */
16772800Skrishna 		switch (err) {
16782800Skrishna 		case CRYPTO_KEY_HANDLE_INVALID:
16792800Skrishna 		case CRYPTO_SESSION_HANDLE_INVALID:
16802800Skrishna 			s->is_valid_handle = B_FALSE;
16812800Skrishna 			s->do_reauth = B_TRUE;
16822800Skrishna 			rverr = EINVAL;
16832800Skrishna 			break;
16842800Skrishna 		case CRYPTO_PIN_EXPIRED:
16852800Skrishna 		case CRYPTO_PIN_LOCKED:
16862800Skrishna 			rverr = EACCES;
16872800Skrishna 			break;
16882800Skrishna 		case CRYPTO_UNKNOWN_PROVIDER:
16892800Skrishna 			rverr = ENXIO;
16902800Skrishna 			break;
16912800Skrishna 		}
16922800Skrishna 	} else {
16932800Skrishna 		err = crypto_decrypt(&rsa_x509_mech, wrapped_pms_data,
16942800Skrishna 		    privkey, NULL, pms_data, creqp);
16952800Skrishna 	}
1696898Skais 
1697898Skais 	switch (err) {
1698898Skais 	case CRYPTO_SUCCESS:
1699898Skais 		break;
1700898Skais 
1701898Skais 	case CRYPTO_QUEUED:
1702898Skais 		/*
1703898Skais 		 * Finish the master secret then the rest of key material
1704898Skais 		 * derivation later.
1705898Skais 		 */
1706898Skais 		ssl->job.kjob = creq.cr_reqid;
1707898Skais 		ssl->job.buf = buf;
1708898Skais 		ssl->job.buflen = allocated;
1709898Skais 		ssl->hs_waitstate = wait_client_key_done;
1710898Skais 		return (0);
1711898Skais 	default:
1712898Skais #ifdef	DEBUG
1713898Skais 		cmn_err(CE_WARN, "kssl_handle_client_key_exchange: "
1714898Skais 			"crypto_decrypt error 0x%02X", err);
1715898Skais #endif	/* DEBUG */
1716898Skais 		kmem_free(buf, allocated);
17172800Skrishna 		return (rverr);
1718898Skais 	}
1719898Skais 
1720898Skais 	pmslen = pms_data->cd_length;
1721898Skais 	pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen);
1722898Skais 
1723898Skais 	/* generate master key and save it in the ssl sid structure */
1724898Skais 	if (IS_TLS(ssl)) {
1725898Skais 		err = kssl_generate_tls_ms(ssl, pms, pmslen);
1726898Skais 		if (!CRYPTO_ERR(err))
1727898Skais 			err = kssl_generate_tls_keyblock(ssl);
1728898Skais 	} else {
1729898Skais 		kssl_generate_ssl_ms(ssl, pms, pmslen);
1730898Skais 		kssl_generate_keyblock(ssl);
1731898Skais 	}
1732898Skais 
1733898Skais 	if (err == CRYPTO_SUCCESS)
1734898Skais 		ssl->hs_waitstate = wait_change_cipher;
1735898Skais 
1736898Skais 	ssl->activeinput = B_FALSE;
1737898Skais 
1738898Skais 	kmem_free(buf, allocated);
1739898Skais 
1740898Skais 	return (0);
1741898Skais }
1742898Skais 
1743898Skais static int
1744898Skais kssl_handle_finished(ssl_t *ssl, mblk_t *mp, int msglen)
1745898Skais {
1746898Skais 	int err;
1747898Skais 	size_t finish_len;
1748898Skais 	int hashcompare;
1749898Skais 
1750898Skais 	ASSERT(ssl->msg.type == finished);
1751898Skais 	ASSERT(ssl->hs_waitstate == wait_finished);
1752898Skais 
1753898Skais 	if (IS_TLS(ssl))
1754898Skais 		finish_len = TLS_FINISHED_SIZE;
1755898Skais 	else
1756898Skais 		finish_len = KSSL_SSL3_FIN_MSGLEN;
1757898Skais 
1758898Skais 	if (msglen != finish_len) {
1759898Skais 		kssl_send_alert(ssl, alert_fatal, illegal_parameter);
1760898Skais 		return (EBADMSG);
1761898Skais 	}
1762898Skais 
1763898Skais 	if (IS_TLS(ssl)) {
1764898Skais 		hashcompare = bcmp(mp->b_rptr, ssl->hs_hashes.tlshash,
1765898Skais 			finish_len);
1766898Skais 	} else {
1767898Skais 		hashcompare = bcmp(mp->b_rptr, &ssl->hs_hashes, finish_len);
1768898Skais 	}
1769898Skais 
1770898Skais 	/* The handshake hashes should be computed by now */
1771898Skais 	if (hashcompare != 0) {
1772898Skais 		kssl_send_alert(ssl, alert_fatal, handshake_failure);
1773898Skais 		return (EBADMSG);
1774898Skais 	}
1775898Skais 
1776898Skais 	mp->b_rptr += msglen;
1777898Skais 
1778898Skais 	ssl->hs_waitstate = idle_handshake;
1779898Skais 
1780898Skais 	if (ssl->resumed == B_TRUE) {
1781898Skais 		ssl->activeinput = B_FALSE;
1782898Skais 		return (0);
1783898Skais 	}
1784898Skais 
1785898Skais 	err = kssl_send_change_cipher_specs(ssl);
1786898Skais 	if (err != 0) {
1787898Skais 		return (err);
1788898Skais 	}
1789898Skais 	err = kssl_send_finished(ssl, 0);
1790898Skais 	if (err != 0) {
1791898Skais 		return (err);
1792898Skais 	}
1793898Skais 
1794898Skais 	ASSERT(ssl->sid.cached == B_FALSE);
1795898Skais 	ssl->sid.cached = B_TRUE;
1796898Skais 	kssl_cache_sid(&ssl->sid, ssl->kssl_entry);
1797898Skais 	ssl->activeinput = B_FALSE;
1798898Skais 
1799898Skais 	return (0);
1800898Skais }
1801898Skais 
1802898Skais #define	KSSL2_CH_MIN_RECSZ	(9)
1803898Skais 
1804898Skais /*
1805898Skais  * This method is needed to handle clients which send the
1806898Skais  * SSLv2/SSLv3 handshake for backwards compat with SSLv2 servers.
1807898Skais  * We are not really doing SSLv2 here, just handling the header
1808898Skais  * and then switching to SSLv3.
1809898Skais  */
1810898Skais int
1811898Skais kssl_handle_v2client_hello(ssl_t *ssl, mblk_t *mp, int recsz)
1812898Skais {
1813898Skais 	uchar_t *recend;
1814898Skais 	int err;
1815898Skais 	SSL3AlertDescription desc = illegal_parameter;
1816898Skais 	uint_t randlen;
1817898Skais 	uint_t sidlen;
1818898Skais 	uint_t nsuites;
1819898Skais 	uchar_t *suitesp;
1820898Skais 	uchar_t *rand;
1821898Skais 	uint_t i, j;
1822898Skais 	uint16_t suite;
1823898Skais 	int ch_recsz = KSSL2_CH_MIN_RECSZ;
1824898Skais 
1825898Skais 	ASSERT(mp->b_wptr >= mp->b_rptr + recsz);
1826898Skais 	ASSERT(ssl->hs_waitstate == wait_client_hello);
1827898Skais 	ASSERT(ssl->resumed == B_FALSE);
1828898Skais 
1829898Skais 	if (recsz < ch_recsz) {
1830898Skais 		goto falert;
1831898Skais 	}
1832898Skais 
1833898Skais 	MD5Init(&ssl->hs_md5);
1834898Skais 	SHA1Init(&ssl->hs_sha1);
1835898Skais 
1836898Skais 	kssl_update_handshake_hashes(ssl, mp->b_rptr, recsz);
1837898Skais 
1838898Skais 	recend = mp->b_rptr + recsz;
1839898Skais 
1840898Skais 	if (*mp->b_rptr != 1) {
1841898Skais 		goto falert;
1842898Skais 	}
1843898Skais 	mp->b_rptr += 3;
1844898Skais 
1845898Skais 	nsuites = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1];
1846898Skais 	sidlen = ((uint_t)mp->b_rptr[2] << 8) + (uint_t)mp->b_rptr[3];
1847898Skais 	randlen = ((uint_t)mp->b_rptr[4] << 8) + (uint_t)mp->b_rptr[5];
1848898Skais 	if (nsuites % 3 != 0) {
1849898Skais 		KSSL_DEBUG2_IF(kssl_debug,
1850898Skais 			"kssl_handle_v2client_hello nsuites = %d, error.",
1851898Skais 			nsuites);
1852898Skais 		goto falert;
1853898Skais 	}
1854898Skais 	if (randlen < SSL_MIN_CHALLENGE_BYTES ||
1855898Skais 	    randlen > SSL_MAX_CHALLENGE_BYTES) {
1856898Skais 		KSSL_DEBUG2_IF(kssl_debug,
1857898Skais 			"kssl_handle_v2client_hello randlen out of range: %d",
1858898Skais 			randlen);
1859898Skais 		goto falert;
1860898Skais 	}
1861898Skais 	mp->b_rptr += 6;
1862898Skais 	ch_recsz += nsuites + sidlen + randlen;
1863898Skais 	if (recsz != ch_recsz) {
1864898Skais 		goto falert;
1865898Skais 	}
1866898Skais 	suitesp = mp->b_rptr;
1867898Skais 	rand = suitesp + nsuites + sidlen;
1868898Skais 	if (randlen < SSL3_RANDOM_LENGTH) {
1869898Skais 		bzero(ssl->client_random, SSL3_RANDOM_LENGTH);
1870898Skais 	}
1871898Skais 	bcopy(rand, &ssl->client_random[SSL3_RANDOM_LENGTH - randlen],
1872898Skais 	    randlen);
1873898Skais 
1874898Skais 	for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) {
1875898Skais 		suite = ssl->kssl_entry->kssl_cipherSuites[i];
1876898Skais 		for (j = 0; j < nsuites; j += 3) {
1877898Skais 			if (suitesp[j] != 0) {
1878898Skais 				continue;
1879898Skais 			}
1880898Skais 
1881898Skais 			if (suitesp[j + 1] == ((suite >> 8) & 0xff) &&
1882898Skais 			    suitesp[j + 2] == (suite & 0xff)) {
1883898Skais 				break;
1884898Skais 			}
1885898Skais 		}
1886898Skais 		if (j < nsuites) {
1887898Skais 			break;
1888898Skais 		}
1889898Skais 	}
1890898Skais 	if (i == ssl->kssl_entry->kssl_cipherSuites_nentries) {
1891898Skais 		KSSL_DEBUG1_IF(kssl_debug, "kssl_handle_v2client_hello - "
1892898Skais 			"cannot find SSLv2 cipher suite");
1893898Skais 		ssl->activeinput = B_FALSE;
1894898Skais 		return (SSL_MISS);
1895898Skais 	}
1896898Skais 
1897898Skais 	mp->b_rptr = recend;
1898898Skais 
1899898Skais 	for (i = 0; i < cipher_suite_defs_nentries; i++) {
1900898Skais 		if (suite == cipher_suite_defs[i].suite) {
1901898Skais 			break;
1902898Skais 		}
1903898Skais 	}
1904898Skais 
1905898Skais 	ASSERT(i < cipher_suite_defs_nentries);
1906898Skais 
1907898Skais 	ssl->pending_cipher_suite = suite;
1908898Skais 	ssl->pending_malg = cipher_suite_defs[i].malg;
1909898Skais 	ssl->pending_calg = cipher_suite_defs[i].calg;
1910898Skais 	ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz;
1911898Skais 
1912898Skais 	ASSERT(ssl->sid.cached == B_FALSE);
1913898Skais 
1914898Skais 	(void) random_get_pseudo_bytes(ssl->sid.session_id,
1915898Skais 	    SSL3_SESSIONID_BYTES);
1916898Skais 	ssl->sid.client_addr = ssl->faddr;
1917898Skais 	ssl->sid.cipher_suite = suite;
1918898Skais 
1919898Skais 	err = kssl_send_server_hello(ssl);
1920898Skais 	if (err != 0) {
1921898Skais 		return (err);
1922898Skais 	}
1923898Skais 	err = kssl_send_certificate_and_server_hello_done(ssl);
1924898Skais 	if (err != 0) {
1925898Skais 		return (err);
1926898Skais 	}
1927898Skais 	KSSL_COUNTER(full_handshakes, 1);
1928898Skais 	ssl->hs_waitstate = wait_client_key;
1929898Skais 	ssl->activeinput = B_FALSE;
1930898Skais 	return (0);
1931898Skais 
1932898Skais falert:
1933898Skais 	kssl_send_alert(ssl, alert_fatal, desc);
1934898Skais 	ssl->activeinput = B_FALSE;
1935898Skais 	return (EBADMSG);
1936898Skais }
1937898Skais 
1938898Skais /*
1939898Skais  * Call back routine for asynchronously submitted RSA decryption jobs.
1940898Skais  * The routine retreived the pre-master secret, and proceeds to generate
1941898Skais  * the remaining key materials.
1942898Skais  */
1943898Skais static void
1944898Skais kssl_cke_done(void *arg, int status)
1945898Skais {
1946898Skais 	int ret = 0;
1947898Skais 	uchar_t *pms;
1948898Skais 	size_t pmslen;
1949898Skais 	crypto_data_t *pms_data;
1950898Skais 	kssl_cmd_t kssl_cmd = KSSL_CMD_NONE;
1951898Skais 	ssl_t *ssl = (ssl_t *)arg;
1952898Skais 	mblk_t *alertmp;
1953898Skais 	kssl_callback_t cbfn;
1954898Skais 	void *cbarg;
1955898Skais 
1956898Skais 	mutex_enter(&ssl->kssl_lock);
1957898Skais 
1958898Skais 	ASSERT(ssl->msg.type == client_key_exchange);
1959898Skais 	ASSERT(ssl->hs_waitstate == wait_client_key_done);
1960898Skais 
1961898Skais 	if (status != CRYPTO_SUCCESS) {
1962898Skais 		kssl_send_alert(ssl, alert_fatal, decrypt_error);
1963898Skais 		kssl_cmd = KSSL_CMD_SEND;
1964898Skais 		goto out;
1965898Skais 	}
1966898Skais 
1967898Skais 	pms_data = (crypto_data_t *)(ssl->job.buf);
1968898Skais 
1969898Skais 	ASSERT(pms_data != NULL);
1970898Skais 
1971898Skais 	pmslen = pms_data->cd_length;
1972898Skais 	pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen);
1973898Skais 
1974898Skais 	/* generate master key and save it in the ssl sid structure */
1975898Skais 	if (IS_TLS(ssl)) {
1976898Skais 		ret = kssl_generate_tls_ms(ssl, pms, pmslen);
1977898Skais 		if (!CRYPTO_ERR(ret))
1978898Skais 			ret = kssl_generate_tls_keyblock(ssl);
1979898Skais 	} else {
1980898Skais 		kssl_generate_ssl_ms(ssl, pms, pmslen);
1981898Skais 		kssl_generate_keyblock(ssl);
1982898Skais 	}
1983898Skais 
1984898Skais 	if (ret == CRYPTO_SUCCESS)
1985898Skais 		ssl->hs_waitstate = wait_change_cipher;
1986898Skais 
1987898Skais out:
1988898Skais 	kmem_free(ssl->job.buf, ssl->job.buflen);
1989898Skais 
1990898Skais 	ssl->job.kjob = 0;
1991898Skais 	ssl->job.buf = NULL;
1992898Skais 	ssl->job.buflen = 0;
1993898Skais 
1994898Skais 	ssl->activeinput = B_FALSE;
1995898Skais 
1996898Skais 	/* If we're the only ones left, then we won't callback */
1997898Skais 	if (ssl->kssl_refcnt == 1) {
1998898Skais 		mutex_exit(&ssl->kssl_lock);
1999898Skais 		KSSL_SSL_REFRELE(ssl);
2000898Skais 		return;
2001898Skais 	}
2002898Skais 
2003898Skais 	cbfn = ssl->cke_callback_func;
2004898Skais 	cbarg = ssl->cke_callback_arg;
2005898Skais 	alertmp = ssl->alert_sendbuf;
2006898Skais 	ssl->alert_sendbuf = NULL;
2007898Skais 
2008898Skais 	mutex_exit(&ssl->kssl_lock);
2009898Skais 
2010898Skais 	KSSL_SSL_REFRELE(ssl);
2011898Skais 
2012898Skais 	/* Now call the callback routine */
2013898Skais 	(*(cbfn))(cbarg, alertmp, kssl_cmd);
2014898Skais }
2015898Skais 
2016898Skais /*
2017898Skais  * Returns the first complete contiguous record out of rec_ass_head
2018898Skais  * The record is returned in a separate contiguous mblk, rec_ass_head is
2019898Skais  * left pointing to the next record in the queue.
2020898Skais  *
2021898Skais  * The output looks as follows:
2022898Skais  *
2023898Skais  * |--------|---------- .... -----|<---------->|<----------->|--- ... ---|
2024898Skais  * ^        ^                     ^  mac_size     pad_size               ^
2025898Skais  * |        |___ b_rptr  b_wptr __|                                      |
2026898Skais  * |                                                                     |
2027898Skais  * |___ db_base                                                db_lim ___|
2028898Skais  */
2029898Skais mblk_t *
2030898Skais kssl_get_next_record(ssl_t *ssl)
2031898Skais {
2032898Skais 	mblk_t *mp, *retmp;
2033898Skais 	int rhsz = SSL3_HDR_LEN;
2034898Skais 	uint16_t rec_sz;
2035898Skais 	int mpsz, total_size;
2036898Skais 	SSL3ContentType content_type;
2037898Skais 
2038898Skais 	ASSERT(MUTEX_HELD(&ssl->kssl_lock));
2039898Skais 
2040898Skais 	mp = ssl->rec_ass_head;
2041898Skais 	if (mp == NULL)
2042898Skais 		return (NULL);
2043898Skais 
2044898Skais 	/* Fast path: when mp has at least a complete record */
2045898Skais 	if (MBLKL(mp) < rhsz) {
2046898Skais 		/* Not even a complete header in there yet */
2047898Skais 		if (msgdsize(mp) < rhsz) {
2048898Skais 			return (NULL);
2049898Skais 		}
2050898Skais 
2051898Skais 		if (!pullupmsg(mp, rhsz)) {
2052898Skais 			kssl_send_alert(ssl, alert_fatal, internal_error);
2053898Skais 			freemsg(mp);
2054898Skais 			ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
2055898Skais 			return (NULL);
2056898Skais 		}
2057898Skais 	}
2058898Skais 	content_type = (SSL3ContentType)mp->b_rptr[0];
2059898Skais 	if (content_type == content_handshake_v2) {
2060898Skais 		rec_sz = (uint16_t)mp->b_rptr[1];
2061898Skais 		rhsz = 2;
2062898Skais 	} else {
2063898Skais 		uint8_t *rec_sz_p = (uint8_t *)mp->b_rptr + 3;
2064898Skais 		rec_sz = BE16_TO_U16(rec_sz_p);
2065898Skais 	}
2066898Skais 
2067898Skais 	/*
2068898Skais 	 * same tests as above. Only rare very fragmented cases will
2069898Skais 	 * incur the cost of msgdsize() and msgpullup(). Well formed
2070898Skais 	 * packets will fall in the most frequent fast path.
2071898Skais 	 */
2072898Skais 	total_size = rhsz + rec_sz;
2073898Skais 
2074898Skais 	/*
2075898Skais 	 * Missing: defensive against record fabricated with longer than
2076898Skais 	 * MAX record length.
2077898Skais 	 */
2078898Skais 	if (MBLKL(mp) < total_size) {
2079898Skais 		/* Not a complete record yet. Keep accumulating */
2080898Skais 		if (msgdsize(mp) < total_size) {
2081898Skais 			return (NULL);
2082898Skais 		}
2083898Skais 
2084898Skais 		if (!pullupmsg(mp, total_size)) {
2085898Skais 			kssl_send_alert(ssl, alert_fatal, internal_error);
2086898Skais 			freemsg(mp);
2087898Skais 			ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
2088898Skais 			return (NULL);
2089898Skais 		}
2090898Skais 	}
2091898Skais 	mpsz = MBLKL(mp);	/* could've changed after the pullup */
2092898Skais 
2093898Skais 	if (mpsz > total_size) {
2094898Skais 		/* gotta allocate a new block */
2095898Skais 		if ((retmp = dupb(mp)) == NULL) {
2096898Skais 			kssl_send_alert(ssl, alert_fatal, internal_error);
2097898Skais 			freemsg(mp);
2098898Skais 			ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
2099898Skais 			return (NULL);
2100898Skais 		}
2101898Skais 
2102898Skais 		retmp->b_wptr = retmp->b_rptr + total_size;
2103898Skais 		mp->b_rptr += total_size;
2104898Skais 		ssl->rec_ass_head = mp;
2105898Skais 	} else {
2106898Skais 		ASSERT(mpsz == total_size);
2107898Skais 		ssl->rec_ass_head = mp->b_cont;
2108898Skais 		mp->b_cont = NULL;
2109898Skais 		retmp = mp;
2110898Skais 	}
2111898Skais 	/* Adjust the tail */
2112898Skais 	if ((mp = ssl->rec_ass_tail = ssl->rec_ass_head) != NULL) {
2113898Skais 		for (; mp->b_cont != NULL; mp = mp->b_cont) {
2114898Skais 			ssl->rec_ass_tail = mp->b_cont;
2115898Skais 		}
2116898Skais 	}
2117898Skais 
2118898Skais 	return (retmp);
2119898Skais }
2120898Skais 
2121898Skais 
2122898Skais static void
2123898Skais kssl_mblksfree(ssl_t *ssl)
2124898Skais {
2125898Skais 
2126898Skais 	ASSERT(ssl != NULL);
2127898Skais 
2128898Skais 	if (ssl->rec_ass_head != NULL) {
2129898Skais 		freemsg(ssl->rec_ass_head);
2130898Skais 	}
2131898Skais 	ssl->rec_ass_head = NULL;
2132898Skais 	ssl->rec_ass_tail = NULL;
2133898Skais 
2134898Skais 	if (ssl->msg.head != NULL) {
2135898Skais 		freemsg(ssl->msg.head);
2136898Skais 	}
2137898Skais 	ssl->msg.head = NULL;
2138898Skais 	ssl->msg.tail = NULL;
2139898Skais 
2140898Skais 	if (ssl->handshake_sendbuf != NULL) {
2141898Skais 		freemsg(ssl->handshake_sendbuf);
2142898Skais 		ssl->handshake_sendbuf = NULL;
2143898Skais 	}
2144898Skais 	if (ssl->alert_sendbuf != NULL) {
2145898Skais 		freemsg(ssl->alert_sendbuf);
2146898Skais 		ssl->alert_sendbuf = NULL;
2147898Skais 	}
2148898Skais }
2149898Skais 
2150898Skais static void
2151898Skais kssl_specsfree(ssl_t *ssl)
2152898Skais {
2153898Skais 	KSSLCipherSpec *spec = &ssl->spec[KSSL_READ];
2154898Skais 
2155898Skais 	if (spec->cipher_ctx != NULL) {
2156898Skais 		crypto_cancel_ctx(spec->cipher_ctx);
2157898Skais 		spec->cipher_ctx = 0;
2158898Skais 	}
2159898Skais 
2160898Skais 	spec = &ssl->spec[KSSL_WRITE];
2161898Skais 
2162898Skais 	if (spec->cipher_ctx != NULL) {
2163898Skais 		crypto_cancel_ctx(spec->cipher_ctx);
2164898Skais 		spec->cipher_ctx = 0;
2165898Skais 	}
2166898Skais }
2167898Skais 
2168898Skais /*
2169898Skais  * Frees the ssl structure (aka the context of an SSL session).
2170898Skais  * Any pending crypto jobs are cancelled.
2171898Skais  * Any initiated crypto contexts are freed as well.
2172898Skais  */
2173898Skais void
2174898Skais kssl_free_context(ssl_t *ssl)
2175898Skais {
2176898Skais 	ASSERT(ssl != NULL);
2177898Skais 	if (!(MUTEX_HELD(&ssl->kssl_lock))) {
2178898Skais 		/* we're coming from an external API entry point */
2179898Skais 		mutex_enter(&ssl->kssl_lock);
2180898Skais 	}
2181898Skais 
2182898Skais 	if (ssl->job.kjob != NULL) {
2183898Skais 		crypto_cancel_req(ssl->job.kjob);
2184898Skais 		kmem_free(ssl->job.buf, ssl->job.buflen);
2185898Skais 
2186898Skais 		ssl->job.kjob = 0;
2187898Skais 		ssl->job.buf = NULL;
2188898Skais 		ssl->job.buflen = 0;
2189898Skais 	}
2190898Skais 
2191898Skais 	kssl_mblksfree(ssl);
2192898Skais 	kssl_specsfree(ssl);
2193898Skais 
2194898Skais 	KSSL_ENTRY_REFRELE(ssl->kssl_entry);
2195898Skais 	ssl->kssl_entry = NULL;
2196898Skais 
2197898Skais 	mutex_exit(&ssl->kssl_lock);
2198898Skais 
2199898Skais 	kmem_cache_free(kssl_cache, ssl);
2200898Skais 	kssl_cache_count--;
2201898Skais }
2202