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