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