8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / uts / common / inet / kssl / ksslapi.c
blob9110c959b52af3032e012b07f732359a64f27ec6
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
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>
33 #include <inet/common.h>
34 #include <inet/ip.h>
36 #include <sys/systm.h>
37 #include <sys/param.h>
38 #include <sys/tihdr.h>
40 #include "ksslimpl.h"
41 #include "ksslproto.h"
42 #include "ksslapi.h"
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);
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.
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.
71 * The function returns KSSL_NO_PROXY otherwise.
74 kssl_endpt_type_t
75 kssl_check_proxy(struct sockaddr *addr, socklen_t len, void *cookie,
76 kssl_ent_t *ksslent)
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;
87 if (kssl_entry_tab_nentries == 0) {
88 return (KSSL_NO_PROXY);
91 ret = KSSL_NO_PROXY;
92 sin = (struct sockaddr_in *)addr;
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;
101 case sizeof (sin6_t):
102 sin6 = (sin6_t *)sin;
103 in_port = ntohs(sin6->sin6_port);
104 v6addr = &sin6->sin6_addr;
105 break;
107 default:
108 return (ret);
111 mutex_enter(&kssl_tab_mutex);
113 for (i = 0; i < kssl_entry_tab_size; i++) {
114 if ((ep = kssl_entry_tab[i]) == NULL)
115 continue;
117 if (IN6_ARE_ADDR_EQUAL(&ep->ke_laddr, v6addr) ||
118 IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr)) {
120 /* This is an SSL port to fallback to */
121 if (ep->ke_ssl_port == in_port) {
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.
134 if (!kssl_enqueue((kssl_chain_t **)
135 &(ep->ke_fallback_head), cookie)) {
136 break;
139 KSSL_ENTRY_REFHOLD(ep);
140 *ksslent = (kssl_ent_t)ep;
142 ret = KSSL_HAS_PROXY;
143 break;
146 /* This is a proxy port. */
147 if (ep->ke_proxy_port == in_port) {
148 /* Add the caller's cookie to proxies list */
150 if (!kssl_enqueue((kssl_chain_t **)
151 &(ep->ke_proxy_head), cookie)) {
152 break;
156 * Make this look like the SSL port to the
157 * transport below
159 sin->sin_port = htons(ep->ke_ssl_port);
161 KSSL_ENTRY_REFHOLD(ep);
162 *ksslent = (kssl_ent_t)ep;
164 ret = KSSL_IS_PROXY;
165 break;
170 mutex_exit(&kssl_tab_mutex);
171 return (ret);
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.
180 void *
181 kssl_find_fallback(kssl_ent_t ksslent)
183 kssl_entry_t *kssl_entry = (kssl_entry_t *)ksslent;
185 if (kssl_entry->ke_fallback_head != NULL)
186 return (kssl_entry->ke_fallback_head->fallback_bound);
188 KSSL_COUNTER(proxy_fallback_failed, 1);
190 return (NULL);
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.
200 * This routine returns TRUE if the item was either successfully added to
201 * the chain, or is already there. It returns FALSE otherwise.
203 static boolean_t
204 kssl_enqueue(kssl_chain_t **head, void *item)
206 kssl_chain_t *newchain, *cur;
208 /* Lookup the existing entries to avoid duplicates */
209 cur = *head;
210 while (cur != NULL) {
211 if (cur->item == item) {
212 return (B_TRUE);
214 cur = cur->next;
217 newchain = kmem_alloc(sizeof (kssl_chain_t), KM_NOSLEEP);
218 if (newchain == NULL) {
219 return (B_FALSE);
222 newchain->item = item;
223 newchain->next = *head;
224 *head = newchain;
225 return (B_TRUE);
228 static void
229 kssl_dequeue(kssl_chain_t **head, void *item)
231 kssl_chain_t *prev, *cur;
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;
243 prev = cur;
244 cur = cur->next;
249 * Holds the kssl_entry
251 void
252 kssl_hold_ent(kssl_ent_t ksslent)
254 KSSL_ENTRY_REFHOLD((kssl_entry_t *)ksslent);
258 * Releases the kssl_entry
259 * If the caller passes a cookie, then it should be removed from both
260 * proxies and fallbacks chains.
262 void
263 kssl_release_ent(kssl_ent_t ksslent, void *cookie, kssl_endpt_type_t endpt_type)
265 kssl_entry_t *kssl_entry = (kssl_entry_t *)ksslent;
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);
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);
281 KSSL_ENTRY_REFRELE(kssl_entry);
285 * Releases the kssl_context
287 void
288 kssl_release_ctx(kssl_ctx_t ksslctx)
290 kssl_free_context((ssl_t *)ksslctx);
294 * Done with asynchronous processing
296 void
297 kssl_async_done(kssl_ctx_t ksslctx)
299 ssl_t *ssl = (ssl_t *)ksslctx;
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);
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.
323 kssl_cmd_t
324 kssl_input(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp, boolean_t *more,
325 kssl_callback_t cbfn, void *arg)
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;
335 ASSERT(ctx != NULL);
337 if (mp != NULL) {
338 ASSERT(mp->b_prev == NULL && mp->b_next == NULL);
341 ssl = (ssl_t *)(ctx);
343 *decrmp = NULL;
344 *more = B_FALSE;
346 mutex_enter(&ssl->kssl_lock);
348 if (ssl->close_notify_clnt == B_TRUE) {
349 DTRACE_PROBE(kssl_err__close_notify);
350 goto sendnewalert;
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);
358 mutex_exit(&ssl->kssl_lock);
359 return (KSSL_CMD_NONE);
363 * Fast path for complete incoming application_data records on an empty
364 * queue.
365 * This is by far the most frequently encountered case
368 if ((!ssl->activeinput) && (ssl->rec_ass_head == NULL) &&
369 ((mp != NULL) && (mplen = MBLKL(mp)) > SSL3_HDR_LEN)) {
371 DTRACE_PROBE1(kssl_mblk__fast_path, mblk_t *, mp);
372 content_type = (SSL3ContentType)mp->b_rptr[0];
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);
379 if ((mp->b_cont == NULL) && (mplen == rec_sz)) {
381 *decrmp = mp;
382 mutex_exit(&ssl->kssl_lock);
383 return (KSSL_CMD_DELIVER_PROXY);
388 ssl->activeinput = B_TRUE;
389 /* Accumulate at least one record */
390 if (mp != NULL) {
391 KSSL_ENQUEUE_MP(ssl, mp);
392 mp = NULL;
394 recmp = kssl_get_next_record(ssl);
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;
402 /* Not even a complete header yet. wait for the rest */
403 mutex_exit(&ssl->kssl_lock);
404 return (KSSL_CMD_NONE);
407 do {
408 DTRACE_PROBE1(kssl_mblk__kssl_input_cycle, mblk_t *, recmp);
409 content_type = (SSL3ContentType)recmp->b_rptr[0];
411 switch (content_type) {
412 case content_application_data:
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.
421 ssl->activeinput = B_FALSE;
422 if (ssl->hs_waitstate != idle_handshake) {
423 DTRACE_PROBE(kssl_err__waitstate_not_idle);
424 goto sendnewalert;
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:
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.
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);
449 break;
450 default:
451 ssl->activeinput = B_FALSE;
452 DTRACE_PROBE(kssl_err__invalid_content_type);
453 goto sendnewalert;
456 /* Priority to Alert messages */
457 if (ssl->alert_sendbuf != NULL) {
458 DTRACE_PROBE(kssl_err__alert_to_send_cycle);
459 goto sendalert;
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;
469 ssl->handshake_sendbuf = NULL;
471 *more = ((ssl->rec_ass_head != NULL) &&
472 (!ssl->activeinput));
473 mutex_exit(&ssl->kssl_lock);
474 return (kssl_cmd);
477 if (ssl->hs_waitstate == idle_handshake) {
478 *more = ((ssl->rec_ass_head != NULL) &&
479 (!ssl->activeinput));
482 if (outmp != NULL) {
483 *decrmp = outmp;
485 * Don't process any packet after an application_data.
486 * We could well receive the close_notify which should
487 * be handled separately.
489 mutex_exit(&ssl->kssl_lock);
490 return (kssl_cmd);
493 * The current record isn't done yet. Don't start the next one
495 if (ssl->activeinput) {
496 mutex_exit(&ssl->kssl_lock);
497 return (kssl_cmd);
499 } while ((recmp = kssl_get_next_record(ssl)) != NULL);
501 mutex_exit(&ssl->kssl_lock);
502 return (kssl_cmd);
504 sendnewalert:
505 kssl_send_alert(ssl, alert_fatal, unexpected_message);
506 if (mp != NULL) {
507 freeb(mp);
510 sendalert:
511 *decrmp = ssl->alert_sendbuf;
512 ssl->alert_sendbuf = NULL;
513 mutex_exit(&ssl->kssl_lock);
514 return (KSSL_CMD_SEND);
518 * Decrypt and verify the MAC of an incoming chain of application_data record.
519 * Each block has exactly one SSL record.
521 kssl_cmd_t
522 kssl_handle_mblk(kssl_ctx_t ctx, mblk_t **mpp, mblk_t **outmp)
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;
539 ASSERT(ctx != NULL);
541 ssl = (ssl_t *)(ctx);
543 mp = firstmp = *mpp;
544 *outmp = NULL;
545 more:
547 while (mp != NULL) {
548 ASSERT(DB_TYPE(mp) == M_DATA);
550 if (DB_REF(mp) > 1) {
552 * Fortunately copyb() preserves the offset,
553 * tail space and alignment so the copy is
554 * ready to be made an SSL record.
556 if ((copybp = copyb(mp)) == NULL)
557 return (NULL);
559 copybp->b_cont = mp->b_cont;
560 if (mp == firstmp) {
561 *mpp = copybp;
562 } else if (prevmp != NULL) {
563 prevmp->b_cont = copybp;
565 freeb(mp);
566 mp = copybp;
569 DTRACE_PROBE1(kssl_mblk__handle_record_cycle, mblk_t *, mp);
570 content_type = (SSL3ContentType)mp->b_rptr[0];
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;
581 /* Remove this message */
582 if (prevmp != NULL) {
583 prevmp->b_cont = nextmp;
586 * If we had processed blocks that need to
587 * be delivered, then remember that error code
589 if (kssl_cmd == KSSL_CMD_DELIVER_PROXY)
590 deliverit = B_TRUE;
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);
598 if (ssl->alert_sendbuf != NULL) {
599 mp = nextmp;
600 DTRACE_PROBE(kssl_err__alert_after_handle_any);
601 goto sendalert;
603 mutex_exit(&ssl->kssl_lock);
605 if (deliverit) {
606 kssl_cmd = KSSL_CMD_DELIVER_PROXY;
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;
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);
623 mp->b_rptr += SSL3_HDR_LEN;
624 recend = mp->b_rptr + rec_sz;
625 real_recend = recend;
628 * Check the assumption that each mblk contains exactly
629 * one complete SSL record. We bail out if the check fails.
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;
639 spec = &ssl->spec[KSSL_READ];
640 mac_sz = spec->mac_hashsz;
641 if (spec->cipher_ctx != 0) {
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.
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;
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;
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;
686 rec_sz -= pad_sz;
687 recend -= pad_sz;
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;
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;
712 ssl->seq_num[KSSL_READ]++;
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;
722 mp->b_wptr = recend;
724 DTRACE_PROBE1(kssl_mblk__dblk_cooked, mblk_t *, mp);
725 KSSL_COUNTER(appdata_record_ins, 1);
727 prevmp = mp;
728 mp = mp->b_cont;
731 return (kssl_cmd);
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);
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);
745 if (mp) {
746 prevmp = NULL;
747 goto more;
750 return (KSSL_CMD_NONE);
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);
759 ssl->alert_sendbuf = NULL;
760 mutex_exit(&ssl->kssl_lock);
762 if (mp) {
763 prevmp = NULL;
764 goto more;
767 return (kssl_cmd);
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.
781 static kssl_cmd_t
782 kssl_handle_any_record(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp,
783 kssl_callback_t cbfn, void *arg)
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;
799 ASSERT(ctx != NULL);
801 ssl = (ssl_t *)(ctx);
803 *decrmp = NULL;
805 save_rptr = mp->b_rptr;
806 save_wptr = mp->b_wptr;
808 ASSERT(MUTEX_HELD(&ssl->kssl_lock));
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;
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);
837 mp->b_rptr += rhsz;
838 recend = mp->b_rptr + rec_sz;
839 real_recend = recend;
842 * Check the assumption that each mblk contains exactly
843 * one complete SSL record. We bail out if the check fails.
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;
855 spec = &ssl->spec[KSSL_READ];
856 mac_sz = spec->mac_hashsz;
857 if (spec->cipher_ctx != 0) {
859 * The record length must be a multiple of the
860 * block size for block ciphers.
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;
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;
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;
896 rec_sz -= pad_sz;
897 recend -= pad_sz;
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;
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;
923 ssl->seq_num[KSSL_READ]++;
924 DTRACE_PROBE1(kssl_mblk__after_compute_MAC,
925 mblk_t *, mp);
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);
939 if (mp->b_rptr == recend) {
940 mp->b_rptr = real_recend;
941 if (error != 0) {
942 goto error;
944 freeb(mp);
946 if (ssl->hs_waitstate == wait_client_key_done)
947 return (KSSL_CMD_QUEUED);
949 return ((ssl->handshake_sendbuf != NULL) ?
950 KSSL_CMD_SEND : KSSL_CMD_NONE);
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;
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++;
968 ssl->msg.msglen_bytes = msglenb;
969 ssl->msg.msglen = msglen;
970 if (msglenb == 3) {
971 ssl->msg.state = MSG_BODY;
974 if (mp->b_rptr == recend) {
975 mp->b_rptr = real_recend;
976 freeb(mp);
977 return (KSSL_CMD_NONE);
980 ASSERT(ssl->msg.state == MSG_BODY);
982 sz = recend - mp->b_rptr;
984 if (ssl->msg.head == NULL &&
985 ssl->msg.msglen <= sz) {
986 continue;
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;
1001 mp->b_rptr = real_recend;
1002 error = ENOMEM;
1003 KSSL_COUNTER(alloc_fails, 1);
1004 goto error;
1008 mp->b_wptr = recend;
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);
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);
1027 if (ssl->hs_waitstate == wait_client_key_done) {
1028 return (KSSL_CMD_QUEUED);
1029 } else {
1030 return (KSSL_CMD_NONE);
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);
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);
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;
1077 ssl->activeinput = B_FALSE;
1078 freeb(mp);
1079 return (KSSL_CMD_NONE);
1081 mp->b_rptr = real_recend;
1082 DTRACE_PROBE(kssl_err__change_cipher_spec);
1083 goto sendalert;
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;
1094 mp->b_wptr = recend;
1095 *decrmp = mp;
1096 ssl->activeinput = B_FALSE;
1097 return (KSSL_CMD_DELIVER_PROXY);
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;
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;
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);
1134 * Initialize the context of an SSL connection, coming to the specified
1135 * address. The ssl structure is returned held.
1137 kssl_status_t
1138 kssl_init_context(kssl_ent_t kssl_ent, struct sockaddr *addr, int mss,
1139 kssl_ctx_t *kssl_ctxp)
1141 ssl_t *ssl = kmem_cache_alloc(kssl_cache, KM_NOSLEEP);
1142 struct sockaddr_in *sin = (struct sockaddr_in *)addr;
1144 if (ssl == NULL) {
1145 return (KSSL_STS_ERR);
1148 bzero(ssl, sizeof (ssl_t));
1150 ssl->kssl_entry = (kssl_entry_t *)kssl_ent;
1151 KSSL_ENTRY_REFHOLD(ssl->kssl_entry);
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;
1159 ssl->tcp_mss = mss;
1160 ssl->sendalert_level = alert_warning;
1161 ssl->sendalert_desc = close_notify;
1162 ssl->sid.cached = B_FALSE;
1164 *kssl_ctxp = (kssl_ctx_t)ssl;
1165 return (KSSL_STS_OK);
1168 void
1169 kssl_set_mss(kssl_ctx_t ctx, uint32_t mss)
1171 ssl_t *ssl = (ssl_t *)ctx;
1172 ssl->tcp_mss = mss;
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.
1183 mblk_t *
1184 kssl_build_record(kssl_ctx_t ctx, mblk_t *mp)
1186 ssl_t *ssl = (ssl_t *)ctx;
1187 mblk_t *retmp = mp, *bp = mp, *prevbp = mp, *copybp;
1189 ASSERT(ssl != NULL);
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.
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;
1213 ASSERT(mp != NULL);
1214 ASSERT(bp != NULL);
1216 do {
1217 if (DB_REF(bp) > 1) {
1219 * Fortunately copyb() preserves the offset,
1220 * tail space and alignment so the copy is
1221 * ready to be made an SSL record.
1223 if ((copybp = copyb(bp)) == NULL)
1224 return (NULL);
1226 copybp->b_cont = bp->b_cont;
1227 if (bp == mp) {
1228 retmp = copybp;
1229 } else {
1230 prevbp->b_cont = copybp;
1232 freeb(bp);
1233 bp = copybp;
1236 if (kssl_build_single_record(ssl, bp) != KSSL_STS_OK)
1237 return (NULL);
1239 prevbp = bp;
1240 bp = bp->b_cont;
1241 } while (bp != NULL);
1243 return (retmp);
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.
1256 static kssl_status_t
1257 kssl_build_single_record(ssl_t *ssl, mblk_t *mp)
1259 int len;
1260 int reclen;
1261 uchar_t *recstart, *versionp;
1262 KSSLCipherSpec *spec;
1263 int mac_sz;
1264 int pad_sz;
1266 spec = &ssl->spec[KSSL_WRITE];
1267 mac_sz = spec->mac_hashsz;
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);
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);
1279 ASSERT(len > 0);
1281 mutex_enter(&ssl->kssl_lock);
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;
1292 versionp = &recstart[1];
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;
1302 recstart[3] = (reclen >> 8) & 0xff;
1303 recstart[4] = reclen & 0xff;
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);
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);