usr/src/uts/common/inet/kssl/ksslapi.c
changeset 898 64b2a371a6bd
child 1139 513d74957e22
equal deleted inserted replaced
897:8bc35ca89c2f 898:64b2a371a6bd
       
     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, Version 1.0 only
       
     6  * (the "License").  You may not use this file except in compliance
       
     7  * with the License.
       
     8  *
       
     9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
    10  * or http://www.opensolaris.org/os/licensing.
       
    11  * See the License for the specific language governing permissions
       
    12  * and limitations under the License.
       
    13  *
       
    14  * When distributing Covered Code, include this CDDL HEADER in each
       
    15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    16  * If applicable, add the following below this CDDL HEADER, with the
       
    17  * fields enclosed by brackets "[]" replaced with your own identifying
       
    18  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    19  *
       
    20  * CDDL HEADER END
       
    21  */
       
    22 /*
       
    23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
       
    24  * Use is subject to license terms.
       
    25  */
       
    26 
       
    27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
       
    28 
       
    29 #include <sys/types.h>
       
    30 #include <sys/stream.h>
       
    31 #include <sys/strsun.h>
       
    32 #include <sys/cmn_err.h>
       
    33 #include <sys/kmem.h>
       
    34 #include <sys/cpuvar.h>
       
    35 #include <sys/atomic.h>
       
    36 #include <sys/sysmacros.h>
       
    37 
       
    38 #include <inet/common.h>
       
    39 #include <inet/ip.h>
       
    40 #include <inet/ip6.h>
       
    41 
       
    42 #include <sys/systm.h>
       
    43 #include <sys/param.h>
       
    44 #include <sys/tihdr.h>
       
    45 
       
    46 #include "ksslimpl.h"
       
    47 #include "ksslproto.h"
       
    48 #include "ksslapi.h"
       
    49 
       
    50 static kssl_cmd_t kssl_handle_any_record(kssl_ctx_t ctx, mblk_t *mp,
       
    51     mblk_t **decrmp, kssl_callback_t cbfn, void *arg);
       
    52 static boolean_t kssl_enqueue(kssl_chain_t **head, void *item);
       
    53 static void kssl_dequeue(kssl_chain_t **head, void *item);
       
    54 static kssl_status_t kssl_build_single_record(ssl_t *ssl, mblk_t *mp);
       
    55 
       
    56 /*
       
    57  * The socket T_bind_req message is intercepted and re-routed here
       
    58  * to see is there is SSL relevant job to do, based on the kssl config
       
    59  * in the kssl_entry_tab.
       
    60  * Looks up the kernel SSL proxy table, to find an entry that matches the
       
    61  * same serveraddr, and has one of the following two criteria:
       
    62  * 1. in_port is an ssl_port. This endpoint can be used later as a fallback
       
    63  *    to complete connections that cannot be handled by the SSL kernel proxy
       
    64  *    (typically non supported ciphersuite). The cookie for the calling client
       
    65  *    is saved with the kssl_entry to be retrieved for the fallback.
       
    66  *    The function returns KSSL_HAS_PROXY.
       
    67  *
       
    68  * 2. in_port is a proxy port for another ssl port. The ssl port is then
       
    69  *    substituted to the in_port in the bind_req TPI structure, so that
       
    70  *    the bind falls through to the SSL port. At the end of this operation,
       
    71  *    all the packets arriving to the SSL port will be delivered to an
       
    72  *    accepted endpoint child of this bound socket.
       
    73  *    The  kssl_entry_t is returned in *ksslent, for later use by the
       
    74  *    lower modules' SSL hooks that handle the Handshake messages.
       
    75  *    The function returns KSSL_IS_PROXY.
       
    76  *
       
    77  * The function returns KSSL_NO_PROXY otherwise. We do not suppport
       
    78  * IPv6 addresses.
       
    79  */
       
    80 
       
    81 kssl_endpt_type_t
       
    82 kssl_check_proxy(mblk_t *bindmp, void *cookie, kssl_ent_t *ksslent)
       
    83 {
       
    84 	int i;
       
    85 	kssl_endpt_type_t ret;
       
    86 	kssl_entry_t *ep;
       
    87 	sin_t *sin;
       
    88 	struct T_bind_req *tbr;
       
    89 	ipaddr_t v4addr;
       
    90 	in_port_t in_port;
       
    91 
       
    92 	if (kssl_enabled == 0) {
       
    93 		return (KSSL_NO_PROXY);
       
    94 	}
       
    95 
       
    96 	tbr = (struct T_bind_req *)bindmp->b_rptr;
       
    97 
       
    98 	ret = KSSL_NO_PROXY;
       
    99 
       
   100 
       
   101 	switch (tbr->ADDR_length) {
       
   102 	case sizeof (sin_t):
       
   103 		sin = (sin_t *)(bindmp->b_rptr + tbr->ADDR_length);
       
   104 		in_port = ntohs(sin->sin_port);
       
   105 		v4addr = sin->sin_addr.s_addr;
       
   106 		break;
       
   107 
       
   108 	case sizeof (sin6_t):
       
   109 		/* Future support of IPv6 goes here */
       
   110 	default:
       
   111 		/* Should ASSERT() here? */
       
   112 		return (ret);
       
   113 	}
       
   114 
       
   115 	mutex_enter(&kssl_tab_mutex);
       
   116 
       
   117 	for (i = 0; i < kssl_entry_tab_size; i++) {
       
   118 		if ((ep = kssl_entry_tab[i]) == NULL)
       
   119 			continue;
       
   120 
       
   121 		if ((ep->ke_laddr == v4addr) || (ep->ke_laddr == INADDR_ANY)) {
       
   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 		if (endpt_type == KSSL_HAS_PROXY)
       
   303 			ASSERT(kssl_entry->ke_fallback_head != NULL);
       
   304 			kssl_dequeue(
       
   305 			    (kssl_chain_t **)&kssl_entry->ke_fallback_head,
       
   306 			    cookie);
       
   307 	}
       
   308 	KSSL_ENTRY_REFRELE(kssl_entry);
       
   309 }
       
   310 
       
   311 /*
       
   312  * Holds the kssl context
       
   313  */
       
   314 void
       
   315 kssl_hold_ctx(kssl_ctx_t ksslctx)
       
   316 {
       
   317 	ssl_t *ssl = (ssl_t *)ksslctx;
       
   318 
       
   319 	KSSL_SSL_REFHOLD(ssl);
       
   320 }
       
   321 
       
   322 /*
       
   323  * Releases the kssl_context
       
   324  */
       
   325 void
       
   326 kssl_release_ctx(kssl_ctx_t ksslctx)
       
   327 {
       
   328 	KSSL_SSL_REFRELE((ssl_t *)ksslctx);
       
   329 }
       
   330 
       
   331 /*
       
   332  * Packets are accumulated here, if there are packets already queued,
       
   333  * or if the context is active.
       
   334  * The context is active when an incoming record processing function
       
   335  * is already executing on a different thread.
       
   336  * Queued packets are handled either when an mblk arrived and completes
       
   337  * a record, or, when the active context processor finishes the task at
       
   338  * hand.
       
   339  * The caller has to keep calling this routine in a loop until it returns
       
   340  * B_FALSE in *more. The reason for this is SSL3: The protocol
       
   341  * allows the client to send its first application_data message right
       
   342  * after it had sent its Finished message, and not wait for the server
       
   343  * ChangeCipherSpec and Finished. This overlap means we can't batch up
       
   344  * a returned Handshake message to be sent on the wire
       
   345  * with a decrypted application_data to be delivered to the application.
       
   346  */
       
   347 kssl_cmd_t
       
   348 kssl_input(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp, boolean_t *more,
       
   349     kssl_callback_t cbfn, void *arg)
       
   350 {
       
   351 	mblk_t *recmp, *outmp = NULL;
       
   352 	kssl_cmd_t kssl_cmd;
       
   353 	ssl_t *ssl;
       
   354 	uint8_t *rec_sz_p;
       
   355 	int mplen;
       
   356 	SSL3ContentType content_type;
       
   357 	uint16_t rec_sz;
       
   358 
       
   359 	ASSERT(ctx != NULL);
       
   360 
       
   361 	if (mp != NULL) {
       
   362 		ASSERT(mp->b_prev == NULL && mp->b_next == NULL);
       
   363 	}
       
   364 
       
   365 	ssl = (ssl_t *)(ctx);
       
   366 
       
   367 	*decrmp = NULL;
       
   368 	*more = B_FALSE;
       
   369 
       
   370 	mutex_enter(&ssl->kssl_lock);
       
   371 
       
   372 	if (ssl->close_notify == B_TRUE) {
       
   373 		goto sendnewalert;
       
   374 	}
       
   375 
       
   376 	/* Whomever is currently processing this connection will get to this */
       
   377 	if (ssl->activeinput) {
       
   378 		if (mp != NULL) {
       
   379 			KSSL_ENQUEUE_MP(ssl, mp);
       
   380 		}
       
   381 		mutex_exit(&ssl->kssl_lock);
       
   382 		return (KSSL_CMD_NONE);
       
   383 	}
       
   384 
       
   385 	/*
       
   386 	 * Fast path for complete incoming application_data records on an empty
       
   387 	 * queue.
       
   388 	 * This is by far the most frequently encountered case
       
   389 	 */
       
   390 
       
   391 	if ((!ssl->activeinput) && (ssl->rec_ass_head == NULL) &&
       
   392 	    ((mp != NULL) && (mplen = MBLKL(mp)) > SSL3_HDR_LEN)) {
       
   393 
       
   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 				mp->b_flag &= ~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 			goto sendalert;
       
   423 		}
       
   424 		/* Not even a complete header yet. wait for the rest */
       
   425 		mutex_exit(&ssl->kssl_lock);
       
   426 		return (KSSL_CMD_NONE);
       
   427 	}
       
   428 
       
   429 	do {
       
   430 		if ((SSL3ContentType)recmp->b_rptr[0] ==
       
   431 		    content_application_data) {
       
   432 			/*
       
   433 			 * application_data records are decrypted and
       
   434 			 * MAC-verified by the stream head, and in the context
       
   435 			 * a read()'ing thread. This avoids unfairly charging
       
   436 			 * the cost of handling this record on the whole system,
       
   437 			 * and prevents doing it while in the shared IP
       
   438 			 * perimeter.
       
   439 			 */
       
   440 			ssl->activeinput = B_FALSE;
       
   441 			if (ssl->hs_waitstate != idle_handshake) {
       
   442 				goto sendnewalert;
       
   443 			}
       
   444 			outmp = recmp;
       
   445 			kssl_cmd = KSSL_CMD_DELIVER_PROXY;
       
   446 		} else {
       
   447 			/*
       
   448 			 * If we're past the initial handshake, start letting
       
   449 			 * the stream head process all records, in particular
       
   450 			 * the close_notify.
       
   451 			 * This is needed to avoid processing them out of
       
   452 			 * sequence when previous application data packets are
       
   453 			 * waiting to be decrypted/MAC'ed and delivered.
       
   454 			 */
       
   455 			if (ssl->hs_waitstate == idle_handshake) {
       
   456 				ssl->activeinput = B_FALSE;
       
   457 				outmp = recmp;
       
   458 				kssl_cmd = KSSL_CMD_DELIVER_PROXY;
       
   459 			} else {
       
   460 				kssl_cmd = kssl_handle_any_record(ssl, recmp,
       
   461 				    &outmp, cbfn, arg);
       
   462 			}
       
   463 		}
       
   464 
       
   465 		/* Priority to Alert messages */
       
   466 		if (ssl->alert_sendbuf != NULL) {
       
   467 			goto sendalert;
       
   468 		}
       
   469 
       
   470 		/* Then handshake messages */
       
   471 		if (ssl->handshake_sendbuf) {
       
   472 			if (*decrmp != NULL) {
       
   473 				linkb(*decrmp, ssl->handshake_sendbuf);
       
   474 			} else {
       
   475 				*decrmp = ssl->handshake_sendbuf;
       
   476 			}
       
   477 			ssl->handshake_sendbuf = NULL;
       
   478 
       
   479 			*more = ((ssl->rec_ass_head != NULL) &&
       
   480 			    (!ssl->activeinput));
       
   481 			mutex_exit(&ssl->kssl_lock);
       
   482 			return (kssl_cmd);
       
   483 		}
       
   484 
       
   485 		if (ssl->hs_waitstate == idle_handshake) {
       
   486 			*more = ((ssl->rec_ass_head != NULL) &&
       
   487 			    (!ssl->activeinput));
       
   488 		}
       
   489 
       
   490 		if (outmp != NULL) {
       
   491 			*decrmp = outmp;
       
   492 			/*
       
   493 			 * Don't process any packet after an application_data.
       
   494 			 * We could well receive the close_notify which should
       
   495 			 * be handled separately.
       
   496 			 */
       
   497 			mutex_exit(&ssl->kssl_lock);
       
   498 			return (kssl_cmd);
       
   499 		}
       
   500 		/*
       
   501 		 * The current record isn't done yet. Don't start the next one
       
   502 		 */
       
   503 		if (ssl->activeinput) {
       
   504 			mutex_exit(&ssl->kssl_lock);
       
   505 			return (kssl_cmd);
       
   506 		}
       
   507 	} while ((recmp = kssl_get_next_record(ssl)) != NULL);
       
   508 
       
   509 	mutex_exit(&ssl->kssl_lock);
       
   510 	return (kssl_cmd);
       
   511 
       
   512 sendnewalert:
       
   513 	kssl_send_alert(ssl, alert_fatal, unexpected_message);
       
   514 	if (mp != NULL) {
       
   515 		freeb(mp);
       
   516 	}
       
   517 
       
   518 sendalert:
       
   519 	*decrmp = ssl->alert_sendbuf;
       
   520 	ssl->alert_sendbuf = NULL;
       
   521 	mutex_exit(&ssl->kssl_lock);
       
   522 	return (KSSL_CMD_SEND);
       
   523 }
       
   524 
       
   525 /*
       
   526  * Decrypt and verify the MAC of an incoming chain of application_data record.
       
   527  * Each block has exactly one SSL record.
       
   528  * This routine recycles its incoming mblk, and flags it as DBLK_COOKED
       
   529  */
       
   530 kssl_cmd_t
       
   531 kssl_handle_record(kssl_ctx_t ctx, mblk_t **mpp, mblk_t **outmp)
       
   532 {
       
   533 	uchar_t *recend, *rec_sz_p;
       
   534 	uchar_t *real_recend;
       
   535 	mblk_t *prevmp = NULL, *nextmp, *mp = *mpp, *copybp;
       
   536 	int mac_sz;
       
   537 	uchar_t version[2];
       
   538 	uint16_t rec_sz;
       
   539 	SSL3AlertDescription desc;
       
   540 	SSL3ContentType content_type;
       
   541 	ssl_t *ssl;
       
   542 	KSSLCipherSpec *spec;
       
   543 	int error = 0, ret;
       
   544 	kssl_cmd_t kssl_cmd = KSSL_CMD_DELIVER_PROXY;
       
   545 	boolean_t deliverit = B_FALSE;
       
   546 	crypto_data_t cipher_data;
       
   547 
       
   548 	ASSERT(ctx != NULL);
       
   549 
       
   550 	ssl = (ssl_t *)(ctx);
       
   551 
       
   552 	*outmp = NULL;
       
   553 
       
   554 more:
       
   555 
       
   556 	while (mp != NULL) {
       
   557 
       
   558 		if (DB_REF(mp) > 1) {
       
   559 			/*
       
   560 			 * Fortunately copyb() preserves the offset,
       
   561 			 * tail space and alignement so the copy is
       
   562 			 * ready to be made an SSL record.
       
   563 			 */
       
   564 			if ((copybp = copyb(mp)) == NULL)
       
   565 				return (NULL);
       
   566 
       
   567 			copybp->b_cont = mp->b_cont;
       
   568 			if (mp == *mpp) {
       
   569 				*mpp = copybp;
       
   570 			} else {
       
   571 				prevmp->b_cont = copybp;
       
   572 			}
       
   573 			freeb(mp);
       
   574 			mp = copybp;
       
   575 		}
       
   576 
       
   577 		content_type = (SSL3ContentType)mp->b_rptr[0];
       
   578 
       
   579 		if (content_type != content_application_data) {
       
   580 			nextmp = mp->b_cont;
       
   581 
       
   582 			/* Remove this message */
       
   583 			if (prevmp != NULL) {
       
   584 				prevmp->b_cont = nextmp;
       
   585 
       
   586 				/*
       
   587 				 * If we had processed blocks that need to
       
   588 				 * be delivered, then remember that error code
       
   589 				 */
       
   590 				if (kssl_cmd == KSSL_CMD_DELIVER_PROXY)
       
   591 					deliverit = B_TRUE;
       
   592 			}
       
   593 
       
   594 			mutex_enter(&ssl->kssl_lock);
       
   595 			kssl_cmd = kssl_handle_any_record(ssl, mp, outmp,
       
   596 			    NULL, NULL);
       
   597 
       
   598 			if (ssl->alert_sendbuf != NULL) {
       
   599 				goto sendalert;
       
   600 			}
       
   601 			mutex_exit(&ssl->kssl_lock);
       
   602 
       
   603 			if (deliverit) {
       
   604 				kssl_cmd = KSSL_CMD_DELIVER_PROXY;
       
   605 			}
       
   606 
       
   607 			mp = nextmp;
       
   608 			continue;
       
   609 		}
       
   610 
       
   611 		version[0] = mp->b_rptr[1];
       
   612 		version[1] = mp->b_rptr[2];
       
   613 		rec_sz_p = SSL3_REC_SIZE(mp);
       
   614 		rec_sz = BE16_TO_U16(rec_sz_p);
       
   615 
       
   616 		mp->b_rptr += SSL3_HDR_LEN;
       
   617 		recend = mp->b_rptr + rec_sz;
       
   618 		real_recend = recend;
       
   619 
       
   620 		spec = &ssl->spec[KSSL_READ];
       
   621 		mac_sz = spec->mac_hashsz;
       
   622 		if (spec->cipher_ctx != 0) {
       
   623 			cipher_data.cd_format = CRYPTO_DATA_RAW;
       
   624 			cipher_data.cd_offset = 0;
       
   625 			cipher_data.cd_length = rec_sz;
       
   626 			cipher_data.cd_miscdata = NULL;
       
   627 			cipher_data.cd_raw.iov_base = (char *)mp->b_rptr;
       
   628 			cipher_data.cd_raw.iov_len = rec_sz;
       
   629 			error = crypto_decrypt_update(spec->cipher_ctx,
       
   630 			    &cipher_data, NULL, NULL);
       
   631 			if (CRYPTO_ERR(error)) {
       
   632 #ifdef	DEBUG
       
   633 				cmn_err(CE_WARN, "kssl_handle_record: "
       
   634 				    "crypto_decrypt_update failed: 0x%02X",
       
   635 				    error);
       
   636 #endif	/* DEBUG */
       
   637 				KSSL_COUNTER(record_decrypt_failure, 1);
       
   638 				mp->b_rptr = recend;
       
   639 				desc = decrypt_error;
       
   640 				goto makealert;
       
   641 			}
       
   642 		}
       
   643 		if (spec->cipher_type == type_block) {
       
   644 			uint_t pad_sz = recend[-1];
       
   645 			pad_sz++;
       
   646 			if (pad_sz + mac_sz > rec_sz) {
       
   647 				mp->b_rptr = recend;
       
   648 				desc = bad_record_mac;
       
   649 				goto makealert;
       
   650 			}
       
   651 			rec_sz -= pad_sz;
       
   652 			recend -= pad_sz;
       
   653 		}
       
   654 		if (mac_sz != 0) {
       
   655 			uchar_t hash[MAX_HASH_LEN];
       
   656 			if (rec_sz < mac_sz) {
       
   657 				mp->b_rptr = real_recend;
       
   658 				desc = bad_record_mac;
       
   659 				goto makealert;
       
   660 			}
       
   661 			rec_sz -= mac_sz;
       
   662 			recend -= mac_sz;
       
   663 			ret = kssl_compute_record_mac(ssl, KSSL_READ,
       
   664 				ssl->seq_num[KSSL_READ], content_type,
       
   665 				version, mp->b_rptr, rec_sz, hash);
       
   666 			if (ret != CRYPTO_SUCCESS ||
       
   667 			    bcmp(hash, recend, mac_sz)) {
       
   668 				mp->b_rptr = real_recend;
       
   669 				desc = bad_record_mac;
       
   670 #ifdef	DEBUG
       
   671 				cmn_err(CE_WARN, "kssl_handle_record: "
       
   672 					"msg MAC mismatch");
       
   673 #endif	/* DEBUG */
       
   674 				KSSL_COUNTER(verify_mac_failure, 1);
       
   675 				goto makealert;
       
   676 			}
       
   677 			ssl->seq_num[KSSL_READ]++;
       
   678 		}
       
   679 
       
   680 		if (ssl->hs_waitstate != idle_handshake) {
       
   681 			mp->b_rptr = real_recend;
       
   682 			desc = unexpected_message;
       
   683 			goto makealert;
       
   684 		}
       
   685 		mp->b_wptr = recend;
       
   686 
       
   687 		prevmp = mp;
       
   688 		mp = mp->b_cont;
       
   689 	}
       
   690 
       
   691 	KSSL_COUNTER(appdata_record_ins, 1);
       
   692 	return (kssl_cmd);
       
   693 
       
   694 makealert:
       
   695 	nextmp = mp->b_cont;
       
   696 	freeb(mp);
       
   697 	mp = nextmp;
       
   698 	mutex_enter(&ssl->kssl_lock);
       
   699 	kssl_send_alert(ssl, alert_fatal, desc);
       
   700 
       
   701 	if (ssl->alert_sendbuf == NULL) {
       
   702 		/* internal memory allocation failure. just return. */
       
   703 #ifdef	DEBUG
       
   704 		cmn_err(CE_WARN, "kssl_handle_record: "
       
   705 		    "alert message allocation failed");
       
   706 #endif	/* DEBUG */
       
   707 		mutex_exit(&ssl->kssl_lock);
       
   708 
       
   709 		if (mp) {
       
   710 			prevmp = NULL;
       
   711 			goto more;
       
   712 		}
       
   713 
       
   714 		return (KSSL_CMD_NONE);
       
   715 	}
       
   716 	kssl_cmd = KSSL_CMD_SEND;
       
   717 sendalert:
       
   718 	if (*outmp == NULL) {
       
   719 		*outmp = ssl->alert_sendbuf;
       
   720 	} else {
       
   721 		linkb(*outmp, ssl->alert_sendbuf);
       
   722 	}
       
   723 	ssl->alert_sendbuf = NULL;
       
   724 	mutex_exit(&ssl->kssl_lock);
       
   725 
       
   726 	if (mp) {
       
   727 		prevmp = NULL;
       
   728 		goto more;
       
   729 	}
       
   730 
       
   731 	return (kssl_cmd);
       
   732 }
       
   733 /*
       
   734  * This is the routine that handles incoming SSL records.
       
   735  * When called the first time, with a NULL context, this routine expects
       
   736  * a ClientHello SSL Handshake packet and shall allocate a context
       
   737  * of a new SSL connection.
       
   738  * During the rest of the handshake packets, the routine adjusts the
       
   739  * state of the context according to the record received.
       
   740  * After the ChangeCipherSpec message is received, the routine first
       
   741  * decrypts/authenticated the packet using the key materials in the
       
   742  * connection's context.
       
   743  * The return code tells the caller what to do with the returned packet.
       
   744  */
       
   745 static kssl_cmd_t
       
   746 kssl_handle_any_record(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp,
       
   747     kssl_callback_t cbfn, void *arg)
       
   748 {
       
   749 	uchar_t *recend, *rec_sz_p;
       
   750 	uchar_t version[2];
       
   751 	uchar_t *real_recend, *save_rptr, *save_wptr;
       
   752 	int rhsz = SSL3_HDR_LEN;
       
   753 	uint16_t rec_sz;
       
   754 	int sz;
       
   755 	int mac_sz;
       
   756 	SSL3AlertDescription desc;
       
   757 	SSL3AlertLevel level;
       
   758 	SSL3ContentType content_type;
       
   759 	ssl_t *ssl;
       
   760 	KSSLCipherSpec *spec;
       
   761 	int error = 0, ret;
       
   762 
       
   763 	ASSERT(ctx != NULL);
       
   764 
       
   765 	ssl = (ssl_t *)(ctx);
       
   766 
       
   767 	*decrmp = NULL;
       
   768 
       
   769 	save_rptr = mp->b_rptr;
       
   770 	save_wptr = mp->b_wptr;
       
   771 
       
   772 	ASSERT(MUTEX_HELD(&ssl->kssl_lock));
       
   773 
       
   774 	content_type = (SSL3ContentType)mp->b_rptr[0];
       
   775 	if (content_type == content_handshake_v2) {
       
   776 		if (ssl->hs_waitstate == wait_client_hello) {
       
   777 			/* V2 compatible ClientHello */
       
   778 			if (mp->b_rptr[3] == 0x03 &&
       
   779 			    (mp->b_rptr[4] == 0x01 ||
       
   780 				mp->b_rptr[4] == 0x00)) {
       
   781 				ssl->major_version = version[0] = mp->b_rptr[3];
       
   782 				ssl->minor_version = version[1] = mp->b_rptr[4];
       
   783 			} else {
       
   784 			/* We don't support "pure" SSLv2 */
       
   785 				desc = protocol_version;
       
   786 				goto sendalert;
       
   787 			}
       
   788 		}
       
   789 		rec_sz = (uint16_t)mp->b_rptr[1];
       
   790 		rhsz = 2;
       
   791 	} else {
       
   792 		ssl->major_version = version[0] = mp->b_rptr[1];
       
   793 		ssl->minor_version = version[1] = mp->b_rptr[2];
       
   794 		rec_sz_p = SSL3_REC_SIZE(mp);
       
   795 		rec_sz = BE16_TO_U16(rec_sz_p);
       
   796 	}
       
   797 
       
   798 	mp->b_rptr += rhsz;
       
   799 	recend = mp->b_rptr + rec_sz;
       
   800 	real_recend = recend;
       
   801 
       
   802 	spec = &ssl->spec[KSSL_READ];
       
   803 	mac_sz = spec->mac_hashsz;
       
   804 	if (spec->cipher_ctx != 0) {
       
   805 		spec->cipher_data.cd_length = rec_sz;
       
   806 		spec->cipher_data.cd_raw.iov_base = (char *)mp->b_rptr;
       
   807 		spec->cipher_data.cd_raw.iov_len = rec_sz;
       
   808 		error = crypto_decrypt_update(spec->cipher_ctx,
       
   809 		    &spec->cipher_data, NULL, NULL);
       
   810 		if (CRYPTO_ERR(error)) {
       
   811 #ifdef	DEBUG
       
   812 			cmn_err(CE_WARN,
       
   813 				"kssl_handle_any_record: crypto_decrypt_update "
       
   814 				"failed: 0x%02X", error);
       
   815 #endif	/* DEBUG */
       
   816 			KSSL_COUNTER(record_decrypt_failure, 1);
       
   817 			mp->b_rptr = recend;
       
   818 			desc = decrypt_error;
       
   819 			goto sendalert;
       
   820 		}
       
   821 	}
       
   822 	if (spec->cipher_type == type_block) {
       
   823 		uint_t pad_sz = recend[-1];
       
   824 		pad_sz++;
       
   825 		if (pad_sz + mac_sz > rec_sz) {
       
   826 			mp->b_rptr = recend;
       
   827 			desc = bad_record_mac;
       
   828 			goto sendalert;
       
   829 		}
       
   830 		rec_sz -= pad_sz;
       
   831 		recend -= pad_sz;
       
   832 	}
       
   833 	if (mac_sz != 0) {
       
   834 		uchar_t hash[MAX_HASH_LEN];
       
   835 		if (rec_sz < mac_sz) {
       
   836 			mp->b_rptr = real_recend;
       
   837 			desc = bad_record_mac;
       
   838 			goto sendalert;
       
   839 		}
       
   840 		rec_sz -= mac_sz;
       
   841 		recend -= mac_sz;
       
   842 		ret = kssl_compute_record_mac(ssl, KSSL_READ,
       
   843 			ssl->seq_num[KSSL_READ], content_type,
       
   844 			version, mp->b_rptr, rec_sz, hash);
       
   845 		if (ret != CRYPTO_SUCCESS ||
       
   846 		    bcmp(hash, recend, mac_sz)) {
       
   847 			mp->b_rptr = real_recend;
       
   848 			desc = bad_record_mac;
       
   849 #ifdef	DEBUG
       
   850 			cmn_err(CE_WARN, "kssl_handle_any_record: "
       
   851 				"msg MAC mismatch");
       
   852 #endif	/* DEBUG */
       
   853 			KSSL_COUNTER(verify_mac_failure, 1);
       
   854 			goto sendalert;
       
   855 		}
       
   856 		ssl->seq_num[KSSL_READ]++;
       
   857 	}
       
   858 
       
   859 	switch (content_type) {
       
   860 	case content_handshake:
       
   861 		do {
       
   862 			if (error != 0 ||
       
   863 			    /* ignore client renegotiation for now */
       
   864 			    ssl->hs_waitstate == idle_handshake) {
       
   865 				mp->b_rptr = recend;
       
   866 			}
       
   867 			if (mp->b_rptr == recend) {
       
   868 				mp->b_rptr = real_recend;
       
   869 				if (error != 0) {
       
   870 					goto error;
       
   871 				}
       
   872 				freeb(mp);
       
   873 
       
   874 				if (ssl->hs_waitstate == wait_client_key_done)
       
   875 					return (KSSL_CMD_QUEUED);
       
   876 
       
   877 				return ((ssl->handshake_sendbuf != NULL) ?
       
   878 				    KSSL_CMD_SEND : KSSL_CMD_NONE);
       
   879 			}
       
   880 			if (ssl->msg.state < MSG_BODY) {
       
   881 				if (ssl->msg.state == MSG_INIT) {
       
   882 					ssl->msg.type =
       
   883 					    (SSL3HandshakeType)*mp->b_rptr++;
       
   884 					ssl->msg.state = MSG_INIT_LEN;
       
   885 				}
       
   886 				if (ssl->msg.state == MSG_INIT_LEN) {
       
   887 					int msglenb =
       
   888 					    ssl->msg.msglen_bytes;
       
   889 					int msglen = ssl->msg.msglen;
       
   890 					while (mp->b_rptr < recend &&
       
   891 					    msglenb < 3) {
       
   892 						msglen = (msglen << 8) +
       
   893 						    (uint_t)(*mp->b_rptr++);
       
   894 						msglenb++;
       
   895 					}
       
   896 					ssl->msg.msglen_bytes = msglenb;
       
   897 					ssl->msg.msglen = msglen;
       
   898 					if (msglenb == 3) {
       
   899 						ssl->msg.state = MSG_BODY;
       
   900 					}
       
   901 				}
       
   902 				if (mp->b_rptr == recend) {
       
   903 					mp->b_rptr = real_recend;
       
   904 					freeb(mp);
       
   905 					return (KSSL_CMD_NONE);
       
   906 				}
       
   907 			}
       
   908 			ASSERT(ssl->msg.state == MSG_BODY);
       
   909 
       
   910 			sz = recend - mp->b_rptr;
       
   911 
       
   912 			if (ssl->msg.head == NULL &&
       
   913 			    ssl->msg.msglen <= sz) {
       
   914 				continue;
       
   915 			}
       
   916 			if (ssl->msg.head != NULL) {
       
   917 				sz += msgdsize(ssl->msg.head);
       
   918 				if (ssl->msg.msglen <= sz) {
       
   919 					ssl->msg.tail->b_cont = mp;
       
   920 					mp = ssl->msg.head;
       
   921 					ssl->sslcnt = 100;
       
   922 					ssl->msg.head = NULL;
       
   923 					ssl->msg.tail = NULL;
       
   924 					if (pullupmsg(mp, -1)) {
       
   925 						recend = mp->b_rptr + sz;
       
   926 						ASSERT(recend <= mp->b_wptr);
       
   927 						continue;
       
   928 					}
       
   929 					mp->b_rptr = real_recend;
       
   930 					error = ENOMEM;
       
   931 					KSSL_COUNTER(alloc_fails, 1);
       
   932 					goto error;
       
   933 				}
       
   934 			}
       
   935 
       
   936 			mp->b_wptr = recend;
       
   937 
       
   938 			if (ssl->msg.head == NULL) {
       
   939 				ssl->msg.head = mp;
       
   940 				ssl->msg.tail = mp;
       
   941 				return (KSSL_CMD_NONE);
       
   942 			} else {
       
   943 				ssl->msg.tail->b_cont = mp;
       
   944 				ssl->msg.tail = mp;
       
   945 				return (KSSL_CMD_NONE);
       
   946 			}
       
   947 		} while (kssl_handle_handshake_message(ssl, mp, &error, cbfn,
       
   948 		    arg));
       
   949 		if (error == SSL_MISS) {
       
   950 			mp->b_rptr = save_rptr;
       
   951 			mp->b_wptr = save_wptr;
       
   952 			KSSL_COUNTER(fallback_connections, 1);
       
   953 			return (KSSL_CMD_NOT_SUPPORTED);
       
   954 		}
       
   955 		if (ssl->hs_waitstate == wait_client_key_done) {
       
   956 			return (KSSL_CMD_QUEUED);
       
   957 		} else {
       
   958 			return (KSSL_CMD_NONE);
       
   959 		}
       
   960 	case content_alert:
       
   961 		if (rec_sz != 2) {
       
   962 			mp->b_rptr = real_recend;
       
   963 			desc = illegal_parameter;
       
   964 			goto sendalert;
       
   965 		} else {
       
   966 			level = *mp->b_rptr++;
       
   967 			desc = *mp->b_rptr++;
       
   968 			mp->b_rptr = real_recend;
       
   969 			if (level != alert_warning || desc != close_notify) {
       
   970 				if (ssl->sid.cached == B_TRUE) {
       
   971 					kssl_uncache_sid(&ssl->sid,
       
   972 					    ssl->kssl_entry);
       
   973 					ssl->sid.cached = B_FALSE;
       
   974 				}
       
   975 				ssl->fatal_alert = B_TRUE;
       
   976 				error = EBADMSG;
       
   977 				goto error;
       
   978 			} else {
       
   979 				ssl->close_notify = B_TRUE;
       
   980 				ssl->activeinput = B_FALSE;
       
   981 				freeb(mp);
       
   982 				return (KSSL_CMD_NONE);
       
   983 			}
       
   984 		}
       
   985 	case content_change_cipher_spec:
       
   986 		if (ssl->hs_waitstate != wait_change_cipher) {
       
   987 			desc = unexpected_message;
       
   988 		} else if (rec_sz != 1 || *mp->b_rptr != 1) {
       
   989 			desc = illegal_parameter;
       
   990 		} else {
       
   991 			mp->b_rptr = real_recend;
       
   992 			ssl->hs_waitstate = wait_finished;
       
   993 			ssl->seq_num[KSSL_READ] = 0;
       
   994 			if ((error = kssl_spec_init(ssl, KSSL_READ)) != 0) {
       
   995 #ifdef	DEBUG
       
   996 				cmn_err(CE_WARN,
       
   997 					"kssl_spec_init returned error "
       
   998 					"0x%02X", error);
       
   999 #endif	/* DEBUG */
       
  1000 				goto error;
       
  1001 			}
       
  1002 			ssl->activeinput = B_FALSE;
       
  1003 			freeb(mp);
       
  1004 			return (KSSL_CMD_NONE);
       
  1005 		}
       
  1006 		mp->b_rptr = real_recend;
       
  1007 		goto sendalert;
       
  1008 
       
  1009 	case content_application_data:
       
  1010 		if (ssl->hs_waitstate != idle_handshake) {
       
  1011 			mp->b_rptr = real_recend;
       
  1012 			desc = unexpected_message;
       
  1013 			goto sendalert;
       
  1014 		}
       
  1015 		mp->b_wptr = recend;
       
  1016 		*decrmp = mp;
       
  1017 		ssl->activeinput = B_FALSE;
       
  1018 		return (KSSL_CMD_DELIVER_PROXY);
       
  1019 
       
  1020 	case content_handshake_v2:
       
  1021 		error = kssl_handle_v2client_hello(ssl, mp, rec_sz);
       
  1022 		if (error == SSL_MISS) {
       
  1023 			mp->b_rptr = save_rptr;
       
  1024 			mp->b_wptr = save_wptr;
       
  1025 			KSSL_COUNTER(fallback_connections, 1);
       
  1026 			return (KSSL_CMD_NOT_SUPPORTED);
       
  1027 		} else if (error != 0) {
       
  1028 			goto error;
       
  1029 		}
       
  1030 		freeb(mp);
       
  1031 		return (KSSL_CMD_SEND);
       
  1032 	default:
       
  1033 		mp->b_rptr = real_recend;
       
  1034 		desc = unexpected_message;
       
  1035 		break;
       
  1036 	}
       
  1037 
       
  1038 sendalert:
       
  1039 	kssl_send_alert(ssl, alert_fatal, desc);
       
  1040 	*decrmp = ssl->alert_sendbuf;
       
  1041 	ssl->alert_sendbuf = NULL;
       
  1042 	freeb(mp);
       
  1043 	return ((*decrmp != NULL) ? KSSL_CMD_SEND : KSSL_CMD_NONE);
       
  1044 error:
       
  1045 	freeb(mp);
       
  1046 	return (KSSL_CMD_NONE);
       
  1047 }
       
  1048 
       
  1049 /*
       
  1050  * Initialize the context of an SSL connection, coming to the specified
       
  1051  * address.
       
  1052  * the ssl structure returned is held.
       
  1053  */
       
  1054 kssl_status_t
       
  1055 kssl_init_context(kssl_ent_t kssl_ent, ipaddr_t faddr, int mss,
       
  1056     kssl_ctx_t *kssl_ctxp)
       
  1057 {
       
  1058 	ssl_t *ssl = kmem_cache_alloc(kssl_cache, KM_NOSLEEP);
       
  1059 
       
  1060 	if (ssl == NULL) {
       
  1061 		return (KSSL_STS_ERR);
       
  1062 	}
       
  1063 
       
  1064 	kssl_cache_count++;
       
  1065 
       
  1066 	bzero(ssl, sizeof (ssl_t));
       
  1067 
       
  1068 	ssl->kssl_entry = (kssl_entry_t *)kssl_ent;
       
  1069 	KSSL_ENTRY_REFHOLD(ssl->kssl_entry);
       
  1070 
       
  1071 	ssl->faddr = faddr;
       
  1072 	ssl->tcp_mss = mss;
       
  1073 	ssl->sendalert_level = alert_warning;
       
  1074 	ssl->sendalert_desc = close_notify;
       
  1075 	ssl->sid.cached = B_FALSE;
       
  1076 
       
  1077 	*kssl_ctxp = (kssl_ctx_t)ssl;
       
  1078 	KSSL_SSL_REFHOLD(ssl);
       
  1079 	return (KSSL_STS_OK);
       
  1080 }
       
  1081 
       
  1082 /*
       
  1083  * Builds SSL records out of the chain of mblks, and returns it.
       
  1084  * Taked a copy of the message before encypting it if it has another
       
  1085  * reference.
       
  1086  * In case of failure, NULL is returned, and the message will be
       
  1087  * freed by the caller.
       
  1088  * A NULL mp means a close_notify is requested.
       
  1089  */
       
  1090 mblk_t *
       
  1091 kssl_build_record(kssl_ctx_t ctx, mblk_t *mp)
       
  1092 {
       
  1093 	ssl_t *ssl = (ssl_t *)ctx;
       
  1094 	mblk_t *retmp = mp, *bp = mp, *prevbp = mp, *copybp;
       
  1095 
       
  1096 	ASSERT(ssl != NULL);
       
  1097 	ASSERT(mp != NULL);
       
  1098 
       
  1099 	do {
       
  1100 		if (DB_REF(bp) > 1) {
       
  1101 			/*
       
  1102 			 * Fortunately copyb() preserves the offset,
       
  1103 			 * tail space and alignement so the copy is
       
  1104 			 * ready to be made an SSL record.
       
  1105 			 */
       
  1106 			if ((copybp = copyb(bp)) == NULL)
       
  1107 				return (NULL);
       
  1108 
       
  1109 			copybp->b_cont = bp->b_cont;
       
  1110 			if (bp == mp) {
       
  1111 				retmp = copybp;
       
  1112 			} else {
       
  1113 				prevbp->b_cont = copybp;
       
  1114 			}
       
  1115 			freeb(bp);
       
  1116 			bp = copybp;
       
  1117 		}
       
  1118 
       
  1119 		if (kssl_build_single_record(ssl, bp) != KSSL_STS_OK)
       
  1120 			return (NULL);
       
  1121 
       
  1122 		prevbp = bp;
       
  1123 		bp = bp->b_cont;
       
  1124 	} while (bp != NULL);
       
  1125 
       
  1126 	return (retmp);
       
  1127 }
       
  1128 
       
  1129 /*
       
  1130  * Builds a single SSL record
       
  1131  * In-line encryption of the record.
       
  1132  */
       
  1133 static kssl_status_t
       
  1134 kssl_build_single_record(ssl_t *ssl, mblk_t *mp)
       
  1135 {
       
  1136 	int len;
       
  1137 	int reclen = 0;
       
  1138 	uchar_t *recstart, *versionp;
       
  1139 	KSSLCipherSpec *spec;
       
  1140 	int mac_sz;
       
  1141 	int pad_sz = 0;
       
  1142 
       
  1143 
       
  1144 	spec = &ssl->spec[KSSL_WRITE];
       
  1145 	mac_sz = spec->mac_hashsz;
       
  1146 
       
  1147 
       
  1148 	ASSERT(DB_REF(mp) == 1);
       
  1149 	ASSERT((mp->b_rptr - mp->b_datap->db_base >= SSL3_HDR_LEN) &&
       
  1150 	    (mp->b_datap->db_lim - mp->b_wptr >= mac_sz + spec->cipher_bsize));
       
  1151 
       
  1152 	len = MBLKL(mp);
       
  1153 
       
  1154 	ASSERT(len > 0);
       
  1155 
       
  1156 	mutex_enter(&ssl->kssl_lock);
       
  1157 
       
  1158 	recstart = mp->b_rptr = mp->b_rptr - SSL3_HDR_LEN;
       
  1159 	recstart[0] = content_application_data;
       
  1160 	recstart[1] = ssl->major_version;
       
  1161 	recstart[2] = ssl->minor_version;
       
  1162 	versionp = &recstart[1];
       
  1163 
       
  1164 	reclen = len + mac_sz;
       
  1165 	if (spec->cipher_type == type_block) {
       
  1166 		pad_sz = spec->cipher_bsize -
       
  1167 		    (reclen & (spec->cipher_bsize - 1));
       
  1168 		ASSERT(reclen + pad_sz <=
       
  1169 		    SSL3_MAX_RECORD_LENGTH);
       
  1170 		reclen += pad_sz;
       
  1171 	}
       
  1172 	recstart[3] = (reclen >> 8) & 0xff;
       
  1173 	recstart[4] = reclen & 0xff;
       
  1174 
       
  1175 	if (kssl_mac_encrypt_record(ssl, content_application_data, versionp,
       
  1176 	    recstart, mp) != 0) {
       
  1177 		/* Do we need an internal_error Alert here? */
       
  1178 		mutex_exit(&ssl->kssl_lock);
       
  1179 		return (KSSL_STS_ERR);
       
  1180 	}
       
  1181 
       
  1182 	KSSL_COUNTER(appdata_record_outs, 1);
       
  1183 	mutex_exit(&ssl->kssl_lock);
       
  1184 	return (KSSL_STS_OK);
       
  1185 }