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