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