xref: /titanic_50/usr/src/uts/common/inet/kssl/ksslapi.c (revision 7ff836697c120cb94bd30d5c2204eb9b74718e4c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/stream.h>
28 #include <sys/strsun.h>
29 #include <sys/kmem.h>
30 #include <sys/cpuvar.h>
31 #include <sys/atomic.h>
32 #include <sys/sysmacros.h>
33 
34 #include <inet/common.h>
35 #include <inet/ip.h>
36 #include <inet/ip6.h>
37 
38 #include <sys/systm.h>
39 #include <sys/param.h>
40 #include <sys/tihdr.h>
41 
42 #include "ksslimpl.h"
43 #include "ksslproto.h"
44 #include "ksslapi.h"
45 
46 static kssl_cmd_t kssl_handle_any_record(kssl_ctx_t ctx, mblk_t *mp,
47     mblk_t **decrmp, kssl_callback_t cbfn, void *arg);
48 static boolean_t kssl_enqueue(kssl_chain_t **head, void *item);
49 static void kssl_dequeue(kssl_chain_t **head, void *item);
50 static kssl_status_t kssl_build_single_record(ssl_t *ssl, mblk_t *mp);
51 
52 /*
53  * The socket T_bind_req message is intercepted and re-routed here
54  * to see is there is SSL relevant job to do, based on the kssl config
55  * in the kssl_entry_tab.
56  * Looks up the kernel SSL proxy table, to find an entry that matches the
57  * same serveraddr, and has one of the following two criteria:
58  * 1. in_port is an ssl_port. This endpoint can be used later as a fallback
59  *    to complete connections that cannot be handled by the SSL kernel proxy
60  *    (typically non supported ciphersuite). The cookie for the calling client
61  *    is saved with the kssl_entry to be retrieved for the fallback.
62  *    The function returns KSSL_HAS_PROXY.
63  *
64  * 2. in_port is a proxy port for another ssl port. The ssl port is then
65  *    substituted to the in_port in the bind_req TPI structure, so that
66  *    the bind falls through to the SSL port. At the end of this operation,
67  *    all the packets arriving to the SSL port will be delivered to an
68  *    accepted endpoint child of this bound socket.
69  *    The  kssl_entry_t is returned in *ksslent, for later use by the
70  *    lower modules' SSL hooks that handle the Handshake messages.
71  *    The function returns KSSL_IS_PROXY.
72  *
73  * The function returns KSSL_NO_PROXY otherwise. We do not suppport
74  * IPv6 addresses.
75  */
76 
77 kssl_endpt_type_t
78 kssl_check_proxy(mblk_t *bindmp, void *cookie, kssl_ent_t *ksslent)
79 {
80 	int i;
81 	kssl_endpt_type_t ret;
82 	kssl_entry_t *ep;
83 	sin_t *sin;
84 	sin6_t *sin6;
85 	struct T_bind_req *tbr;
86 	ipaddr_t v4addr;
87 	in_port_t in_port;
88 
89 	if (kssl_enabled == 0) {
90 		return (KSSL_NO_PROXY);
91 	}
92 
93 	tbr = (struct T_bind_req *)bindmp->b_rptr;
94 
95 	ret = KSSL_NO_PROXY;
96 
97 	sin = (sin_t *)(bindmp->b_rptr + tbr->ADDR_offset);
98 
99 	switch (tbr->ADDR_length) {
100 	case sizeof (sin_t):
101 		in_port = ntohs(sin->sin_port);
102 		v4addr = sin->sin_addr.s_addr;
103 		break;
104 
105 	case sizeof (sin6_t):
106 		/*
107 		 * Handle any IPv4-mapped IPv6 address for now.
108 		 * Support of IPv6 will be added later.
109 		 */
110 		sin6 = (sin6_t *)sin;
111 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
112 			in_port = ntohs(sin6->sin6_port);
113 			IN6_V4MAPPED_TO_IPADDR(&sin6->sin6_addr, v4addr);
114 			break;
115 		}
116 
117 		/* fallthrough for normal IPv6 address */
118 	default:
119 		return (ret);
120 	}
121 
122 	mutex_enter(&kssl_tab_mutex);
123 
124 	for (i = 0; i < kssl_entry_tab_size; i++) {
125 		if ((ep = kssl_entry_tab[i]) == NULL)
126 			continue;
127 
128 		if ((ep->ke_laddr == v4addr) || (ep->ke_laddr == INADDR_ANY)) {
129 
130 			/* This is an SSL port to fallback to */
131 			if (ep->ke_ssl_port == in_port) {
132 
133 				/*
134 				 * Let's see first if there's at least
135 				 * an endpoint for a proxy server.
136 				 * If there's none, then we return as we have
137 				 * no proxy, so that the bind() to the
138 				 * transport layer goes through.
139 				 * The calling module will ask for this
140 				 * cookie if it wants to fall back to it,
141 				 * so add this one to the list of fallback
142 				 * clients.
143 				 */
144 				if (!kssl_enqueue((kssl_chain_t **)
145 				    &(ep->ke_fallback_head), cookie)) {
146 					break;
147 				}
148 
149 				/*
150 				 * Now transform the T_BIND_REQ into
151 				 * a T_BIND_ACK.
152 				 */
153 				tbr->PRIM_type = T_BIND_ACK;
154 				bindmp->b_datap->db_type = M_PCPROTO;
155 
156 				KSSL_ENTRY_REFHOLD(ep);
157 				*ksslent = (kssl_ent_t)ep;
158 
159 				ret = KSSL_HAS_PROXY;
160 				break;
161 			}
162 
163 			/* This is a proxy port. */
164 			if (ep->ke_proxy_port == in_port) {
165 				mblk_t *entmp;
166 
167 				/* Append this entry to the bind_req mblk */
168 
169 				entmp = allocb(sizeof (kssl_entry_t),
170 				    BPRI_MED);
171 				if (entmp == NULL)
172 					break;
173 				*((kssl_entry_t **)entmp->b_rptr) = ep;
174 
175 				entmp->b_wptr = entmp->b_rptr +
176 				    sizeof (kssl_entry_t);
177 
178 				bindmp->b_cont = entmp;
179 
180 				/* Add the caller's cookie to proxies list */
181 
182 				if (!kssl_enqueue((kssl_chain_t **)
183 				    &(ep->ke_proxy_head), cookie)) {
184 					freeb(bindmp->b_cont);
185 					bindmp->b_cont = NULL;
186 					break;
187 				}
188 
189 				/*
190 				 * Make this look  like the SSL port to the
191 				 * transport below
192 				 */
193 				sin->sin_port = htons(ep->ke_ssl_port);
194 
195 				tbr->PRIM_type = T_SSL_PROXY_BIND_REQ;
196 
197 				KSSL_ENTRY_REFHOLD(ep);
198 				*ksslent = (kssl_ent_t)ep;
199 
200 				ret = KSSL_IS_PROXY;
201 				break;
202 			}
203 		}
204 	}
205 
206 	mutex_exit(&kssl_tab_mutex);
207 	return (ret);
208 }
209 
210 /*
211  * Retrieved an endpoint "bound" to the SSL entry.
212  * Such endpoint has previously called kssl_check_proxy(), got itself
213  * linked to the kssl_entry's ke_fallback_head list.
214  * This routine returns the cookie from that SSL entry ke_fallback_head list.
215  */
216 void *
217 kssl_find_fallback(kssl_ent_t ksslent)
218 {
219 	kssl_entry_t *kssl_entry = (kssl_entry_t *)ksslent;
220 
221 	if (kssl_entry->ke_fallback_head != NULL)
222 		return (kssl_entry->ke_fallback_head->fallback_bound);
223 
224 	KSSL_COUNTER(proxy_fallback_failed, 1);
225 
226 	return (NULL);
227 }
228 
229 /*
230  * Re-usable code for adding and removing an element to/from a chain that
231  * matches "item"
232  * The chain is simple-linked and NULL ended.
233  */
234 
235 /*
236  * This routine returns TRUE if the item was either successfully added to
237  * the chain, or is already there. It returns FALSE otherwise.
238  */
239 static boolean_t
240 kssl_enqueue(kssl_chain_t **head, void *item)
241 {
242 	kssl_chain_t *newchain, *cur;
243 
244 	/* Lookup the existing entries to avoid duplicates */
245 	cur = *head;
246 	while (cur != NULL) {
247 		if (cur->item == item) {
248 			return (B_TRUE);
249 		}
250 		cur = cur->next;
251 	}
252 
253 	newchain = kmem_alloc(sizeof (kssl_chain_t), KM_NOSLEEP);
254 	if (newchain == NULL) {
255 		return (B_FALSE);
256 	}
257 
258 	newchain->item = item;
259 	newchain->next = *head;
260 	*head = newchain;
261 	return (B_TRUE);
262 }
263 
264 static void
265 kssl_dequeue(kssl_chain_t **head, void *item)
266 {
267 	kssl_chain_t *prev, *cur;
268 
269 	prev = cur = *head;
270 	while (cur != NULL) {
271 		if (cur->item == item) {
272 			if (cur == *head)
273 				*head = (*head)->next;
274 			else
275 				prev->next = cur->next;
276 			kmem_free(cur, sizeof (kssl_chain_t));
277 			return;
278 		}
279 		prev = cur;
280 		cur = cur->next;
281 	}
282 }
283 
284 /*
285  * Holds the kssl_entry
286  */
287 void
288 kssl_hold_ent(kssl_ent_t ksslent)
289 {
290 	KSSL_ENTRY_REFHOLD((kssl_entry_t *)ksslent);
291 }
292 
293 /*
294  * Releases the kssl_entry
295  * If the caller passes a cookie, then it should be removed from both
296  * proxies and fallbacks chains.
297  */
298 void
299 kssl_release_ent(kssl_ent_t ksslent, void *cookie, kssl_endpt_type_t endpt_type)
300 {
301 	kssl_entry_t *kssl_entry = (kssl_entry_t *)ksslent;
302 
303 	if (cookie != NULL) {
304 		if (endpt_type == KSSL_IS_PROXY)
305 			ASSERT(kssl_entry->ke_proxy_head != NULL);
306 			kssl_dequeue(
307 			    (kssl_chain_t **)&kssl_entry->ke_proxy_head,
308 			    cookie);
309 		if (endpt_type == KSSL_HAS_PROXY)
310 			ASSERT(kssl_entry->ke_fallback_head != NULL);
311 			kssl_dequeue(
312 			    (kssl_chain_t **)&kssl_entry->ke_fallback_head,
313 			    cookie);
314 	}
315 	KSSL_ENTRY_REFRELE(kssl_entry);
316 }
317 
318 /*
319  * Holds the kssl context
320  */
321 void
322 kssl_hold_ctx(kssl_ctx_t ksslctx)
323 {
324 	ssl_t *ssl = (ssl_t *)ksslctx;
325 
326 	KSSL_SSL_REFHOLD(ssl);
327 }
328 
329 /*
330  * Releases the kssl_context
331  */
332 void
333 kssl_release_ctx(kssl_ctx_t ksslctx)
334 {
335 	KSSL_SSL_REFRELE((ssl_t *)ksslctx);
336 }
337 
338 /*
339  * Packets are accumulated here, if there are packets already queued,
340  * or if the context is active.
341  * The context is active when an incoming record processing function
342  * is already executing on a different thread.
343  * Queued packets are handled either when an mblk arrived and completes
344  * a record, or, when the active context processor finishes the task at
345  * hand.
346  * The caller has to keep calling this routine in a loop until it returns
347  * B_FALSE in *more. The reason for this is SSL3: The protocol
348  * allows the client to send its first application_data message right
349  * after it had sent its Finished message, and not wait for the server
350  * ChangeCipherSpec and Finished. This overlap means we can't batch up
351  * a returned Handshake message to be sent on the wire
352  * with a decrypted application_data to be delivered to the application.
353  */
354 kssl_cmd_t
355 kssl_input(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp, boolean_t *more,
356     kssl_callback_t cbfn, void *arg)
357 {
358 	mblk_t *recmp, *outmp = NULL;
359 	kssl_cmd_t kssl_cmd;
360 	ssl_t *ssl;
361 	uint8_t *rec_sz_p;
362 	int mplen;
363 	SSL3ContentType content_type;
364 	uint16_t rec_sz;
365 
366 	ASSERT(ctx != NULL);
367 
368 	if (mp != NULL) {
369 		ASSERT(mp->b_prev == NULL && mp->b_next == NULL);
370 	}
371 
372 	ssl = (ssl_t *)(ctx);
373 
374 	*decrmp = NULL;
375 	*more = B_FALSE;
376 
377 	mutex_enter(&ssl->kssl_lock);
378 
379 	if (ssl->close_notify == B_TRUE) {
380 		DTRACE_PROBE(kssl_err__close_notify);
381 		goto sendnewalert;
382 	}
383 
384 	/* Whomever is currently processing this connection will get to this */
385 	if (ssl->activeinput) {
386 		if (mp != NULL) {
387 			KSSL_ENQUEUE_MP(ssl, mp);
388 		}
389 		mutex_exit(&ssl->kssl_lock);
390 		return (KSSL_CMD_NONE);
391 	}
392 
393 	/*
394 	 * Fast path for complete incoming application_data records on an empty
395 	 * queue.
396 	 * This is by far the most frequently encountered case
397 	 */
398 
399 	if ((!ssl->activeinput) && (ssl->rec_ass_head == NULL) &&
400 	    ((mp != NULL) && (mplen = MBLKL(mp)) > SSL3_HDR_LEN)) {
401 
402 		DTRACE_PROBE1(kssl_mblk__fast_path, mblk_t *, mp);
403 		content_type = (SSL3ContentType)mp->b_rptr[0];
404 
405 		if ((content_type == content_application_data) &&
406 		    (ssl->hs_waitstate == idle_handshake)) {
407 			rec_sz_p = SSL3_REC_SIZE(mp);
408 			rec_sz = BE16_TO_U16(rec_sz_p);
409 
410 			if ((mp->b_cont == NULL) && (mplen == rec_sz)) {
411 
412 				DB_FLAGS(mp) &= ~DBLK_COOKED;
413 				*decrmp = mp;
414 				mutex_exit(&ssl->kssl_lock);
415 				return (KSSL_CMD_DELIVER_PROXY);
416 			}
417 		}
418 	}
419 
420 	ssl->activeinput = B_TRUE;
421 	/* Accumulate at least one record */
422 	if (mp != NULL) {
423 		KSSL_ENQUEUE_MP(ssl, mp);
424 		mp = NULL;
425 	}
426 	recmp = kssl_get_next_record(ssl);
427 
428 	if (recmp == NULL) {
429 		ssl->activeinput = B_FALSE;
430 		if (ssl->alert_sendbuf != NULL) {
431 			DTRACE_PROBE(kssl_err__alert_to_send);
432 			goto sendalert;
433 		}
434 		/* Not even a complete header yet. wait for the rest */
435 		mutex_exit(&ssl->kssl_lock);
436 		return (KSSL_CMD_NONE);
437 	}
438 
439 	do {
440 		DTRACE_PROBE1(kssl_mblk__kssl_input_cycle, mblk_t *, recmp);
441 		content_type = (SSL3ContentType)recmp->b_rptr[0];
442 
443 		switch (content_type) {
444 		case content_application_data:
445 			/*
446 			 * application_data records are decrypted and
447 			 * MAC-verified by the stream head, and in the context
448 			 * a read()'ing thread. This avoids unfairly charging
449 			 * the cost of handling this record on the whole system,
450 			 * and prevents doing it while in the shared IP
451 			 * perimeter.
452 			 */
453 			ssl->activeinput = B_FALSE;
454 			if (ssl->hs_waitstate != idle_handshake) {
455 				DTRACE_PROBE(kssl_err__waitstate_not_idle);
456 				goto sendnewalert;
457 			}
458 			outmp = recmp;
459 			kssl_cmd = KSSL_CMD_DELIVER_PROXY;
460 			break;
461 		case content_change_cipher_spec:
462 		case content_alert:
463 		case content_handshake:
464 		case content_handshake_v2:
465 			/*
466 			 * If we're past the initial handshake, start letting
467 			 * the stream head process all records, in particular
468 			 * the close_notify.
469 			 * This is needed to avoid processing them out of
470 			 * sequence when previous application data packets are
471 			 * waiting to be decrypted/MAC'ed and delivered.
472 			 */
473 			if (ssl->hs_waitstate == idle_handshake) {
474 				ssl->activeinput = B_FALSE;
475 				outmp = recmp;
476 				kssl_cmd = KSSL_CMD_DELIVER_PROXY;
477 			} else {
478 				kssl_cmd = kssl_handle_any_record(ssl, recmp,
479 				    &outmp, cbfn, arg);
480 			}
481 			break;
482 		default:
483 			ssl->activeinput = B_FALSE;
484 			DTRACE_PROBE(kssl_err__invalid_content_type);
485 			goto sendnewalert;
486 		}
487 
488 		/* Priority to Alert messages */
489 		if (ssl->alert_sendbuf != NULL) {
490 			DTRACE_PROBE(kssl_err__alert_to_send_cycle);
491 			goto sendalert;
492 		}
493 
494 		/* Then handshake messages */
495 		if (ssl->handshake_sendbuf) {
496 			if (*decrmp != NULL) {
497 				linkb(*decrmp, ssl->handshake_sendbuf);
498 			} else {
499 				*decrmp = ssl->handshake_sendbuf;
500 			}
501 			ssl->handshake_sendbuf = NULL;
502 
503 			*more = ((ssl->rec_ass_head != NULL) &&
504 			    (!ssl->activeinput));
505 			mutex_exit(&ssl->kssl_lock);
506 			return (kssl_cmd);
507 		}
508 
509 		if (ssl->hs_waitstate == idle_handshake) {
510 			*more = ((ssl->rec_ass_head != NULL) &&
511 			    (!ssl->activeinput));
512 		}
513 
514 		if (outmp != NULL) {
515 			*decrmp = outmp;
516 			/*
517 			 * Don't process any packet after an application_data.
518 			 * We could well receive the close_notify which should
519 			 * be handled separately.
520 			 */
521 			mutex_exit(&ssl->kssl_lock);
522 			return (kssl_cmd);
523 		}
524 		/*
525 		 * The current record isn't done yet. Don't start the next one
526 		 */
527 		if (ssl->activeinput) {
528 			mutex_exit(&ssl->kssl_lock);
529 			return (kssl_cmd);
530 		}
531 	} while ((recmp = kssl_get_next_record(ssl)) != NULL);
532 
533 	mutex_exit(&ssl->kssl_lock);
534 	return (kssl_cmd);
535 
536 sendnewalert:
537 	kssl_send_alert(ssl, alert_fatal, unexpected_message);
538 	if (mp != NULL) {
539 		freeb(mp);
540 	}
541 
542 sendalert:
543 	*decrmp = ssl->alert_sendbuf;
544 	ssl->alert_sendbuf = NULL;
545 	mutex_exit(&ssl->kssl_lock);
546 	return (KSSL_CMD_SEND);
547 }
548 
549 /*
550  * Process mblk b_cont chain returned from stream head. The chain could
551  * contain a mixture (albeit continuous) of processed and unprocessed
552  * mblks. This situation could happen when more data was available in
553  * stream head queue than requested. In such case the rest of processed
554  * data would be putback().
555  *
556  * Processed mblks in this function contain either a full or partial portion
557  * of a decrypted and verified SSL record. The former case is produced
558  * by the function itself, the latter case is explained above.
559  *
560  * In case of unprocessed mblks, decrypt and verify the MAC of an incoming
561  * chain of application_data record. Each block has exactly one SSL record.
562  * This routine recycles incoming mblks, and flags them as DBLK_COOKED.
563  */
564 kssl_cmd_t
565 kssl_handle_mblk(kssl_ctx_t ctx, mblk_t **mpp, mblk_t **outmp)
566 {
567 	uchar_t *recend, *rec_sz_p;
568 	uchar_t *real_recend;
569 	mblk_t *prevmp = NULL, *nextmp, *firstmp, *mp, *copybp;
570 	int mac_sz;
571 	uchar_t version[2];
572 	uint16_t rec_sz;
573 	SSL3AlertDescription desc;
574 	SSL3ContentType content_type;
575 	ssl_t *ssl;
576 	KSSLCipherSpec *spec;
577 	int error = 0, ret;
578 	kssl_cmd_t kssl_cmd = KSSL_CMD_DELIVER_PROXY;
579 	boolean_t deliverit = B_FALSE;
580 	crypto_data_t cipher_data;
581 
582 	ASSERT(ctx != NULL);
583 
584 	ssl = (ssl_t *)(ctx);
585 
586 	mp = firstmp = *mpp;
587 	*outmp = NULL;
588 
589 	/*
590 	 * Skip over already processed mblks. This prevents a case where
591 	 * struiocopyout() copies unprocessed data to userland.
592 	 */
593 	while ((mp != NULL) && (DB_FLAGS(mp) & DBLK_COOKED)) {
594 		ASSERT(DB_TYPE(mp) == M_DATA);
595 		DTRACE_PROBE1(kssl_mblk__already_processed_mblk, mblk_t *, mp);
596 		mp = mp->b_cont;
597 	}
598 
599 more:
600 
601 	while (mp != NULL) {
602 		/* only unprocessed mblks should reach us */
603 		ASSERT(DB_TYPE(mp) == M_DATA);
604 		ASSERT(!(DB_FLAGS(mp) & DBLK_COOKED));
605 
606 		if (DB_REF(mp) > 1) {
607 			/*
608 			 * Fortunately copyb() preserves the offset,
609 			 * tail space and alignement so the copy is
610 			 * ready to be made an SSL record.
611 			 */
612 			if ((copybp = copyb(mp)) == NULL)
613 				return (NULL);
614 
615 			copybp->b_cont = mp->b_cont;
616 			if (mp == firstmp) {
617 				*mpp = copybp;
618 			} else if (prevmp != NULL) {
619 				prevmp->b_cont = copybp;
620 			}
621 			freeb(mp);
622 			mp = copybp;
623 		}
624 
625 		DTRACE_PROBE1(kssl_mblk__handle_record_cycle, mblk_t *, mp);
626 		content_type = (SSL3ContentType)mp->b_rptr[0];
627 
628 		switch (content_type) {
629 		case content_application_data:
630 			break;
631 		case content_change_cipher_spec:
632 		case content_alert:
633 		case content_handshake:
634 		case content_handshake_v2:
635 			nextmp = mp->b_cont;
636 
637 			/* Remove this message */
638 			if (prevmp != NULL) {
639 				prevmp->b_cont = nextmp;
640 
641 				/*
642 				 * If we had processed blocks that need to
643 				 * be delivered, then remember that error code
644 				 */
645 				if (kssl_cmd == KSSL_CMD_DELIVER_PROXY)
646 					deliverit = B_TRUE;
647 			}
648 
649 			mutex_enter(&ssl->kssl_lock);
650 			/* NOTE: This routine could free mp. */
651 			kssl_cmd = kssl_handle_any_record(ssl, mp, outmp,
652 			    NULL, NULL);
653 
654 			if (ssl->alert_sendbuf != NULL) {
655 				mp = nextmp;
656 				DTRACE_PROBE(kssl_err__alert_after_handle_any);
657 				goto sendalert;
658 			}
659 			mutex_exit(&ssl->kssl_lock);
660 
661 			if (deliverit) {
662 				kssl_cmd = KSSL_CMD_DELIVER_PROXY;
663 			}
664 
665 			mp = nextmp;
666 			continue;	/* to the while loop */
667 		default:
668 			desc = decode_error;
669 			KSSL_COUNTER(internal_errors, 1);
670 			DTRACE_PROBE(kssl_err__decode_error);
671 			goto makealert;
672 		}
673 
674 		version[0] = mp->b_rptr[1];
675 		version[1] = mp->b_rptr[2];
676 		rec_sz_p = SSL3_REC_SIZE(mp);
677 		rec_sz = BE16_TO_U16(rec_sz_p);
678 
679 		mp->b_rptr += SSL3_HDR_LEN;
680 		recend = mp->b_rptr + rec_sz;
681 		real_recend = recend;
682 
683 		/*
684 		 * Check the assumption that each mblk contains exactly
685 		 * one complete SSL record. We bail out if the check fails.
686 		 */
687 		ASSERT(recend == mp->b_wptr);
688 		if (recend != mp->b_wptr) {
689 			desc = decode_error;
690 			KSSL_COUNTER(internal_errors, 1);
691 			DTRACE_PROBE(kssl_err__not_complete_record);
692 			goto makealert;
693 		}
694 
695 		spec = &ssl->spec[KSSL_READ];
696 		mac_sz = spec->mac_hashsz;
697 		if (spec->cipher_ctx != 0) {
698 
699 			/*
700 			 * The record length must be a multiple of the
701 			 * block size for block ciphers.
702 			 * The cipher_bsize is always a power of 2.
703 			 */
704 			if ((spec->cipher_type == type_block) &&
705 			    ((rec_sz & (spec->cipher_bsize - 1)) != 0)) {
706 				DTRACE_PROBE2(kssl_err__bad_record_size,
707 				    uint16_t, rec_sz,
708 				    int, spec->cipher_bsize);
709 				KSSL_COUNTER(record_decrypt_failure, 1);
710 				mp->b_rptr = recend;
711 				desc = decrypt_error;
712 				goto makealert;
713 			}
714 
715 			cipher_data.cd_format = CRYPTO_DATA_RAW;
716 			cipher_data.cd_offset = 0;
717 			cipher_data.cd_length = rec_sz;
718 			cipher_data.cd_miscdata = NULL;
719 			cipher_data.cd_raw.iov_base = (char *)mp->b_rptr;
720 			cipher_data.cd_raw.iov_len = rec_sz;
721 			error = crypto_decrypt_update(spec->cipher_ctx,
722 			    &cipher_data, NULL, NULL);
723 			if (CRYPTO_ERR(error)) {
724 				DTRACE_PROBE1(
725 				    kssl_err__crypto_decrypt_update_failed,
726 				    int, error);
727 				KSSL_COUNTER(record_decrypt_failure, 1);
728 				mp->b_rptr = recend;
729 				desc = decrypt_error;
730 				goto makealert;
731 			}
732 		}
733 		if (spec->cipher_type == type_block) {
734 			uint_t pad_sz = recend[-1];
735 			pad_sz++;
736 			if (pad_sz + mac_sz > rec_sz) {
737 				DTRACE_PROBE(kssl_err__pad_mac_bigger);
738 				mp->b_rptr = recend;
739 				desc = bad_record_mac;
740 				goto makealert;
741 			}
742 			rec_sz -= pad_sz;
743 			recend -= pad_sz;
744 		}
745 		if (mac_sz != 0) {
746 			uchar_t hash[MAX_HASH_LEN];
747 			if (rec_sz < mac_sz) {
748 				DTRACE_PROBE(kssl_err__pad_smaller_mac);
749 				mp->b_rptr = real_recend;
750 				desc = bad_record_mac;
751 				goto makealert;
752 			}
753 			rec_sz -= mac_sz;
754 			recend -= mac_sz;
755 			ret = kssl_compute_record_mac(ssl, KSSL_READ,
756 			    ssl->seq_num[KSSL_READ], content_type,
757 			    version, mp->b_rptr, rec_sz, hash);
758 			if (ret != CRYPTO_SUCCESS ||
759 			    bcmp(hash, recend, mac_sz)) {
760 				DTRACE_PROBE1(kssl_mblk__MACmismatch_handlerec,
761 				    mblk_t *, mp);
762 				mp->b_rptr = real_recend;
763 				desc = bad_record_mac;
764 				DTRACE_PROBE(kssl_err__msg_MAC_mismatch);
765 				KSSL_COUNTER(verify_mac_failure, 1);
766 				goto makealert;
767 			}
768 			ssl->seq_num[KSSL_READ]++;
769 		}
770 
771 		if (ssl->hs_waitstate != idle_handshake) {
772 			DTRACE_PROBE1(kssl_err__unexpected_msg,
773 			    SSL3WaitState, ssl->hs_waitstate);
774 			mp->b_rptr = real_recend;
775 			desc = unexpected_message;
776 			goto makealert;
777 		}
778 		mp->b_wptr = recend;
779 
780 		DB_FLAGS(mp) |= DBLK_COOKED;
781 		DTRACE_PROBE1(kssl_mblk__dblk_cooked, mblk_t *, mp);
782 		KSSL_COUNTER(appdata_record_ins, 1);
783 
784 		prevmp = mp;
785 		mp = mp->b_cont;
786 	}
787 
788 	return (kssl_cmd);
789 
790 makealert:
791 	nextmp = mp->b_cont;
792 	freeb(mp);
793 	mp = nextmp;
794 	mutex_enter(&ssl->kssl_lock);
795 	kssl_send_alert(ssl, alert_fatal, desc);
796 
797 	if (ssl->alert_sendbuf == NULL) {
798 		/* internal memory allocation failure. just return. */
799 		DTRACE_PROBE(kssl_err__alert_msg_alloc_failed);
800 		mutex_exit(&ssl->kssl_lock);
801 
802 		if (mp) {
803 			prevmp = NULL;
804 			goto more;
805 		}
806 
807 		return (KSSL_CMD_NONE);
808 	}
809 	kssl_cmd = KSSL_CMD_SEND;
810 sendalert:
811 	if (*outmp == NULL) {
812 		*outmp = ssl->alert_sendbuf;
813 	} else {
814 		linkb(*outmp, ssl->alert_sendbuf);
815 	}
816 	ssl->alert_sendbuf = NULL;
817 	mutex_exit(&ssl->kssl_lock);
818 
819 	if (mp) {
820 		prevmp = NULL;
821 		goto more;
822 	}
823 
824 	return (kssl_cmd);
825 }
826 /*
827  * This is the routine that handles incoming SSL records.
828  * When called the first time, with a NULL context, this routine expects
829  * a ClientHello SSL Handshake packet and shall allocate a context
830  * of a new SSL connection.
831  * During the rest of the handshake packets, the routine adjusts the
832  * state of the context according to the record received.
833  * After the ChangeCipherSpec message is received, the routine first
834  * decrypts/authenticated the packet using the key materials in the
835  * connection's context.
836  * The return code tells the caller what to do with the returned packet.
837  */
838 static kssl_cmd_t
839 kssl_handle_any_record(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp,
840     kssl_callback_t cbfn, void *arg)
841 {
842 	uchar_t *recend, *rec_sz_p;
843 	uchar_t version[2];
844 	uchar_t *real_recend, *save_rptr, *save_wptr;
845 	int rhsz = SSL3_HDR_LEN;
846 	uint16_t rec_sz;
847 	int sz;
848 	int mac_sz;
849 	SSL3AlertDescription desc;
850 	SSL3AlertLevel level;
851 	SSL3ContentType content_type;
852 	ssl_t *ssl;
853 	KSSLCipherSpec *spec;
854 	int error = 0, ret;
855 
856 	ASSERT(ctx != NULL);
857 
858 	ssl = (ssl_t *)(ctx);
859 
860 	*decrmp = NULL;
861 
862 	save_rptr = mp->b_rptr;
863 	save_wptr = mp->b_wptr;
864 
865 	ASSERT(MUTEX_HELD(&ssl->kssl_lock));
866 
867 	content_type = (SSL3ContentType)mp->b_rptr[0];
868 	if (content_type == content_handshake_v2) {
869 		if (ssl->hs_waitstate == wait_client_hello) {
870 			/* V2 compatible ClientHello */
871 			if (mp->b_rptr[3] == 0x03 &&
872 			    (mp->b_rptr[4] == 0x01 ||
873 			    mp->b_rptr[4] == 0x00)) {
874 				ssl->major_version = version[0] = mp->b_rptr[3];
875 				ssl->minor_version = version[1] = mp->b_rptr[4];
876 			} else {
877 			/* We don't support "pure" SSLv2 */
878 				DTRACE_PROBE(kssl_err__no_SSLv2);
879 				desc = protocol_version;
880 				goto sendalert;
881 			}
882 		}
883 		rec_sz = (uint16_t)mp->b_rptr[1];
884 		rhsz = 2;
885 	} else {
886 		ssl->major_version = version[0] = mp->b_rptr[1];
887 		ssl->minor_version = version[1] = mp->b_rptr[2];
888 		rec_sz_p = SSL3_REC_SIZE(mp);
889 		rec_sz = BE16_TO_U16(rec_sz_p);
890 	}
891 
892 	mp->b_rptr += rhsz;
893 	recend = mp->b_rptr + rec_sz;
894 	real_recend = recend;
895 
896 	/*
897 	 * Check the assumption that each mblk contains exactly
898 	 * one complete SSL record. We bail out if the check fails.
899 	 */
900 	ASSERT(recend == mp->b_wptr);
901 	if (recend != mp->b_wptr) {
902 		DTRACE_PROBE3(kssl_mblk__handle_any_record_recszerr,
903 		    mblk_t *, mp, int, rhsz, int, rec_sz);
904 		DTRACE_PROBE(kssl_err__record_size);
905 		desc = decode_error;
906 		KSSL_COUNTER(internal_errors, 1);
907 		goto sendalert;
908 	}
909 
910 	spec = &ssl->spec[KSSL_READ];
911 	mac_sz = spec->mac_hashsz;
912 	if (spec->cipher_ctx != 0) {
913 		/*
914 		 * The record length must be a multiple of the
915 		 * block size for block ciphers.
916 		 */
917 		if ((spec->cipher_type == type_block) &&
918 		    ((rec_sz & (spec->cipher_bsize - 1)) != 0)) {
919 			DTRACE_PROBE2(kssl_err__bad_record_size,
920 			    uint16_t, rec_sz, int, spec->cipher_bsize);
921 			KSSL_COUNTER(record_decrypt_failure, 1);
922 			mp->b_rptr = recend;
923 			desc = decrypt_error;
924 			goto sendalert;
925 		}
926 
927 		spec->cipher_data.cd_length = rec_sz;
928 		spec->cipher_data.cd_raw.iov_base = (char *)mp->b_rptr;
929 		spec->cipher_data.cd_raw.iov_len = rec_sz;
930 		error = crypto_decrypt_update(spec->cipher_ctx,
931 		    &spec->cipher_data, NULL, NULL);
932 		if (CRYPTO_ERR(error)) {
933 			DTRACE_PROBE1(kssl_err__crypto_decrypt_update_failed,
934 			    int, error);
935 			KSSL_COUNTER(record_decrypt_failure, 1);
936 			mp->b_rptr = recend;
937 			desc = decrypt_error;
938 			goto sendalert;
939 		}
940 	}
941 	if (spec->cipher_type == type_block) {
942 		uint_t pad_sz = recend[-1];
943 		pad_sz++;
944 		if (pad_sz + mac_sz > rec_sz) {
945 			DTRACE_PROBE2(kssl_err__pad_mac_mismatch,
946 			    int, pad_sz, int, mac_sz);
947 			mp->b_rptr = recend;
948 			desc = bad_record_mac;
949 			goto sendalert;
950 		}
951 		rec_sz -= pad_sz;
952 		recend -= pad_sz;
953 	}
954 	if (mac_sz != 0) {
955 		uchar_t hash[MAX_HASH_LEN];
956 		if (rec_sz < mac_sz) {
957 			DTRACE_PROBE1(kssl_err__mac_size_too_big,
958 			    int, mac_sz);
959 			mp->b_rptr = real_recend;
960 			desc = bad_record_mac;
961 			goto sendalert;
962 		}
963 		rec_sz -= mac_sz;
964 		recend -= mac_sz;
965 		ret = kssl_compute_record_mac(ssl, KSSL_READ,
966 		    ssl->seq_num[KSSL_READ], content_type,
967 		    version, mp->b_rptr, rec_sz, hash);
968 		if (ret != CRYPTO_SUCCESS ||
969 		    bcmp(hash, recend, mac_sz)) {
970 			DTRACE_PROBE1(kssl_mblk__MACmismatch_anyrecord,
971 			    mblk_t *, mp);
972 			mp->b_rptr = real_recend;
973 			desc = bad_record_mac;
974 			DTRACE_PROBE(kssl_err__msg_MAC_mismatch);
975 			KSSL_COUNTER(verify_mac_failure, 1);
976 			goto sendalert;
977 		}
978 		ssl->seq_num[KSSL_READ]++;
979 		DTRACE_PROBE1(kssl_mblk__after_compute_MAC,
980 		    mblk_t *, mp);
981 	}
982 
983 	switch (content_type) {
984 	case content_handshake:
985 		do {
986 			DTRACE_PROBE1(kssl_mblk__content_handshake_cycle,
987 			    mblk_t *, mp);
988 			if (error != 0 ||
989 			    /* ignore client renegotiation for now */
990 			    ssl->hs_waitstate == idle_handshake) {
991 				mp->b_rptr = recend;
992 			}
993 			if (mp->b_rptr == recend) {
994 				mp->b_rptr = real_recend;
995 				if (error != 0) {
996 					goto error;
997 				}
998 				freeb(mp);
999 
1000 				if (ssl->hs_waitstate == wait_client_key_done)
1001 					return (KSSL_CMD_QUEUED);
1002 
1003 				return ((ssl->handshake_sendbuf != NULL) ?
1004 				    KSSL_CMD_SEND : KSSL_CMD_NONE);
1005 			}
1006 			if (ssl->msg.state < MSG_BODY) {
1007 				if (ssl->msg.state == MSG_INIT) {
1008 					ssl->msg.type =
1009 					    (SSL3HandshakeType)*mp->b_rptr++;
1010 					ssl->msg.state = MSG_INIT_LEN;
1011 				}
1012 				if (ssl->msg.state == MSG_INIT_LEN) {
1013 					int msglenb =
1014 					    ssl->msg.msglen_bytes;
1015 					int msglen = ssl->msg.msglen;
1016 					while (mp->b_rptr < recend &&
1017 					    msglenb < 3) {
1018 						msglen = (msglen << 8) +
1019 						    (uint_t)(*mp->b_rptr++);
1020 						msglenb++;
1021 					}
1022 					ssl->msg.msglen_bytes = msglenb;
1023 					ssl->msg.msglen = msglen;
1024 					if (msglenb == 3) {
1025 						ssl->msg.state = MSG_BODY;
1026 					}
1027 				}
1028 				if (mp->b_rptr == recend) {
1029 					mp->b_rptr = real_recend;
1030 					freeb(mp);
1031 					return (KSSL_CMD_NONE);
1032 				}
1033 			}
1034 			ASSERT(ssl->msg.state == MSG_BODY);
1035 
1036 			sz = recend - mp->b_rptr;
1037 
1038 			if (ssl->msg.head == NULL &&
1039 			    ssl->msg.msglen <= sz) {
1040 				continue;
1041 			}
1042 			if (ssl->msg.head != NULL) {
1043 				sz += msgdsize(ssl->msg.head);
1044 				if (ssl->msg.msglen <= sz) {
1045 					ssl->msg.tail->b_cont = mp;
1046 					mp = ssl->msg.head;
1047 					ssl->sslcnt = 100;
1048 					ssl->msg.head = NULL;
1049 					ssl->msg.tail = NULL;
1050 					if (pullupmsg(mp, -1)) {
1051 						recend = mp->b_rptr + sz;
1052 						ASSERT(recend <= mp->b_wptr);
1053 						continue;
1054 					}
1055 					mp->b_rptr = real_recend;
1056 					error = ENOMEM;
1057 					KSSL_COUNTER(alloc_fails, 1);
1058 					goto error;
1059 				}
1060 			}
1061 
1062 			mp->b_wptr = recend;
1063 
1064 			if (ssl->msg.head == NULL) {
1065 				ssl->msg.head = mp;
1066 				ssl->msg.tail = mp;
1067 				return (KSSL_CMD_NONE);
1068 			} else {
1069 				ssl->msg.tail->b_cont = mp;
1070 				ssl->msg.tail = mp;
1071 				return (KSSL_CMD_NONE);
1072 			}
1073 		} while (kssl_handle_handshake_message(ssl, mp, &error, cbfn,
1074 		    arg));
1075 		if (error == SSL_MISS) {
1076 			mp->b_rptr = save_rptr;
1077 			mp->b_wptr = save_wptr;
1078 			KSSL_COUNTER(fallback_connections, 1);
1079 			return (KSSL_CMD_NOT_SUPPORTED);
1080 		}
1081 		if (ssl->hs_waitstate == wait_client_key_done) {
1082 			return (KSSL_CMD_QUEUED);
1083 		} else {
1084 			return (KSSL_CMD_NONE);
1085 		}
1086 	case content_alert:
1087 		DTRACE_PROBE1(kssl_mblk__content_alert, mblk_t *, mp);
1088 		if (rec_sz != 2) {
1089 			DTRACE_PROBE(kssl_err__illegal_param);
1090 			mp->b_rptr = real_recend;
1091 			desc = illegal_parameter;
1092 			goto sendalert;
1093 		} else {
1094 			level = *mp->b_rptr++;
1095 			desc = *mp->b_rptr++;
1096 			mp->b_rptr = real_recend;
1097 			if (level != alert_warning || desc != close_notify) {
1098 				if (ssl->sid.cached == B_TRUE) {
1099 					kssl_uncache_sid(&ssl->sid,
1100 					    ssl->kssl_entry);
1101 					ssl->sid.cached = B_FALSE;
1102 				}
1103 				DTRACE_PROBE2(kssl_err__bad_content_alert,
1104 				    SSL3AlertLevel, level,
1105 				    SSL3AlertDescription, desc);
1106 				ssl->fatal_alert = B_TRUE;
1107 				error = EBADMSG;
1108 				goto error;
1109 			} else {
1110 				ssl->close_notify = B_TRUE;
1111 				ssl->activeinput = B_FALSE;
1112 				freeb(mp);
1113 				return (KSSL_CMD_NONE);
1114 			}
1115 		}
1116 	case content_change_cipher_spec:
1117 		DTRACE_PROBE1(kssl_mblk__change_cipher_spec,
1118 		    mblk_t *, mp);
1119 		if (ssl->hs_waitstate != wait_change_cipher) {
1120 			desc = unexpected_message;
1121 		} else if (rec_sz != 1 || *mp->b_rptr != 1) {
1122 			desc = illegal_parameter;
1123 		} else {
1124 			mp->b_rptr = real_recend;
1125 			ssl->hs_waitstate = wait_finished;
1126 			ssl->seq_num[KSSL_READ] = 0;
1127 			if ((error = kssl_spec_init(ssl, KSSL_READ)) != 0) {
1128 				DTRACE_PROBE1(kssl_err__kssl_spec_init_error,
1129 				    int, error);
1130 				goto error;
1131 			}
1132 			ssl->activeinput = B_FALSE;
1133 			freeb(mp);
1134 			return (KSSL_CMD_NONE);
1135 		}
1136 		mp->b_rptr = real_recend;
1137 		DTRACE_PROBE(kssl_err__change_cipher_spec);
1138 		goto sendalert;
1139 
1140 	case content_application_data:
1141 		DTRACE_PROBE1(kssl_mblk__content_app_data,
1142 		    mblk_t *, mp);
1143 		if (ssl->hs_waitstate != idle_handshake) {
1144 			DTRACE_PROBE(kssl_err__content_app_data);
1145 			mp->b_rptr = real_recend;
1146 			desc = unexpected_message;
1147 			goto sendalert;
1148 		}
1149 		mp->b_wptr = recend;
1150 		*decrmp = mp;
1151 		ssl->activeinput = B_FALSE;
1152 		return (KSSL_CMD_DELIVER_PROXY);
1153 
1154 	case content_handshake_v2:
1155 		DTRACE_PROBE1(kssl_mblk__content_handshake_v2,
1156 		    mblk_t *, mp);
1157 		error = kssl_handle_v2client_hello(ssl, mp, rec_sz);
1158 		if (error == SSL_MISS) {
1159 			mp->b_rptr = save_rptr;
1160 			mp->b_wptr = save_wptr;
1161 			KSSL_COUNTER(fallback_connections, 1);
1162 			return (KSSL_CMD_NOT_SUPPORTED);
1163 		} else if (error != 0) {
1164 			DTRACE_PROBE(kssl_err__v2client_hello_failed);
1165 			goto error;
1166 		}
1167 		freeb(mp);
1168 		return (KSSL_CMD_SEND);
1169 	default:
1170 		DTRACE_PROBE1(kssl_mblk__unexpected_msg,
1171 		    mblk_t *, mp);
1172 		mp->b_rptr = real_recend;
1173 		desc = unexpected_message;
1174 		break;
1175 	}
1176 
1177 sendalert:
1178 	kssl_send_alert(ssl, alert_fatal, desc);
1179 	*decrmp = ssl->alert_sendbuf;
1180 	ssl->alert_sendbuf = NULL;
1181 	freeb(mp);
1182 	return ((*decrmp != NULL) ? KSSL_CMD_SEND : KSSL_CMD_NONE);
1183 error:
1184 	freeb(mp);
1185 	return (KSSL_CMD_NONE);
1186 }
1187 
1188 /*
1189  * Initialize the context of an SSL connection, coming to the specified
1190  * address.
1191  * the ssl structure returned is held.
1192  */
1193 kssl_status_t
1194 kssl_init_context(kssl_ent_t kssl_ent, ipaddr_t faddr, int mss,
1195     kssl_ctx_t *kssl_ctxp)
1196 {
1197 	ssl_t *ssl = kmem_cache_alloc(kssl_cache, KM_NOSLEEP);
1198 
1199 	if (ssl == NULL) {
1200 		return (KSSL_STS_ERR);
1201 	}
1202 
1203 	kssl_cache_count++;
1204 
1205 	bzero(ssl, sizeof (ssl_t));
1206 
1207 	ssl->kssl_entry = (kssl_entry_t *)kssl_ent;
1208 	KSSL_ENTRY_REFHOLD(ssl->kssl_entry);
1209 
1210 	ssl->faddr = faddr;
1211 	ssl->tcp_mss = mss;
1212 	ssl->sendalert_level = alert_warning;
1213 	ssl->sendalert_desc = close_notify;
1214 	ssl->sid.cached = B_FALSE;
1215 
1216 	*kssl_ctxp = (kssl_ctx_t)ssl;
1217 	KSSL_SSL_REFHOLD(ssl);
1218 	return (KSSL_STS_OK);
1219 }
1220 
1221 /*
1222  * Builds SSL records out of the chain of mblks, and returns it.
1223  * Taked a copy of the message before encypting it if it has another
1224  * reference.
1225  * In case of failure, NULL is returned, and the message will be
1226  * freed by the caller.
1227  * A NULL mp means a close_notify is requested.
1228  */
1229 mblk_t *
1230 kssl_build_record(kssl_ctx_t ctx, mblk_t *mp)
1231 {
1232 	ssl_t *ssl = (ssl_t *)ctx;
1233 	mblk_t *retmp = mp, *bp = mp, *prevbp = mp, *copybp;
1234 
1235 	ASSERT(ssl != NULL);
1236 	ASSERT(mp != NULL);
1237 
1238 	do {
1239 		if (DB_REF(bp) > 1) {
1240 			/*
1241 			 * Fortunately copyb() preserves the offset,
1242 			 * tail space and alignement so the copy is
1243 			 * ready to be made an SSL record.
1244 			 */
1245 			if ((copybp = copyb(bp)) == NULL)
1246 				return (NULL);
1247 
1248 			copybp->b_cont = bp->b_cont;
1249 			if (bp == mp) {
1250 				retmp = copybp;
1251 			} else {
1252 				prevbp->b_cont = copybp;
1253 			}
1254 			freeb(bp);
1255 			bp = copybp;
1256 		}
1257 
1258 		if (kssl_build_single_record(ssl, bp) != KSSL_STS_OK)
1259 			return (NULL);
1260 
1261 		prevbp = bp;
1262 		bp = bp->b_cont;
1263 	} while (bp != NULL);
1264 
1265 	return (retmp);
1266 }
1267 
1268 /*
1269  * Builds a single SSL record
1270  * In-line encryption of the record.
1271  */
1272 static kssl_status_t
1273 kssl_build_single_record(ssl_t *ssl, mblk_t *mp)
1274 {
1275 	int len;
1276 	int reclen = 0;
1277 	uchar_t *recstart, *versionp;
1278 	KSSLCipherSpec *spec;
1279 	int mac_sz;
1280 	int pad_sz = 0;
1281 
1282 
1283 	spec = &ssl->spec[KSSL_WRITE];
1284 	mac_sz = spec->mac_hashsz;
1285 
1286 
1287 	ASSERT(DB_REF(mp) == 1);
1288 	ASSERT((mp->b_rptr - mp->b_datap->db_base >= SSL3_HDR_LEN) &&
1289 	    (mp->b_datap->db_lim - mp->b_wptr >= mac_sz + spec->cipher_bsize));
1290 
1291 	len = MBLKL(mp);
1292 
1293 	ASSERT(len > 0);
1294 
1295 	mutex_enter(&ssl->kssl_lock);
1296 
1297 	recstart = mp->b_rptr = mp->b_rptr - SSL3_HDR_LEN;
1298 	recstart[0] = content_application_data;
1299 	recstart[1] = ssl->major_version;
1300 	recstart[2] = ssl->minor_version;
1301 	versionp = &recstart[1];
1302 
1303 	reclen = len + mac_sz;
1304 	if (spec->cipher_type == type_block) {
1305 		pad_sz = spec->cipher_bsize -
1306 		    (reclen & (spec->cipher_bsize - 1));
1307 		ASSERT(reclen + pad_sz <=
1308 		    SSL3_MAX_RECORD_LENGTH);
1309 		reclen += pad_sz;
1310 	}
1311 	recstart[3] = (reclen >> 8) & 0xff;
1312 	recstart[4] = reclen & 0xff;
1313 
1314 	if (kssl_mac_encrypt_record(ssl, content_application_data, versionp,
1315 	    recstart, mp) != 0) {
1316 		/* Do we need an internal_error Alert here? */
1317 		mutex_exit(&ssl->kssl_lock);
1318 		return (KSSL_STS_ERR);
1319 	}
1320 
1321 	KSSL_COUNTER(appdata_record_outs, 1);
1322 	mutex_exit(&ssl->kssl_lock);
1323 	return (KSSL_STS_OK);
1324 }
1325