diff options
author | jsing <> | 2022-03-14 16:49:35 +0000 |
---|---|---|
committer | jsing <> | 2022-03-14 16:49:35 +0000 |
commit | 07d9625933f5867c4dee9ecde797f4222f5dc516 (patch) | |
tree | f36b60b7bdcf81c644d8d156a92e99f3582d41d0 /src/lib/libssl/d1_pkt.c | |
parent | f3380f46eb991038b5106c03e9edc8021bae09cb (diff) | |
download | openbsd-07d9625933f5867c4dee9ecde797f4222f5dc516.tar.gz openbsd-07d9625933f5867c4dee9ecde797f4222f5dc516.tar.bz2 openbsd-07d9625933f5867c4dee9ecde797f4222f5dc516.zip |
Factor out unexpected handshake message handling code in the legacy stack.
The TLS record layer has to be able to handle unexpected handshake messages
that result when it has been asked to read application data. The way that
this is currently done in the legacy stack is a layering violation - the
record layer knows about DTLS/TLS handshake messages, parsing them and then
deciding what action to take. This is further complicated by the need to
handle handshake message fragments.
For now, factor this code out with minimal changes - since it is a layering
violation we have to retain separate code for DTLS and TLS.
ok beck@ inoguchi@ tb@
Diffstat (limited to 'src/lib/libssl/d1_pkt.c')
-rw-r--r-- | src/lib/libssl/d1_pkt.c | 222 |
1 files changed, 121 insertions, 101 deletions
diff --git a/src/lib/libssl/d1_pkt.c b/src/lib/libssl/d1_pkt.c index 6ed04395b9..f6f07052a1 100644 --- a/src/lib/libssl/d1_pkt.c +++ b/src/lib/libssl/d1_pkt.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: d1_pkt.c,v 1.119 2022/03/12 12:53:03 jsing Exp $ */ | 1 | /* $OpenBSD: d1_pkt.c,v 1.120 2022/03/14 16:49:35 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * DTLS implementation written by Nagendra Modadugu | 3 | * DTLS implementation written by Nagendra Modadugu |
4 | * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. | 4 | * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. |
@@ -482,6 +482,123 @@ dtls1_get_record(SSL *s) | |||
482 | return (1); | 482 | return (1); |
483 | } | 483 | } |
484 | 484 | ||
485 | static int | ||
486 | dtls1_read_handshake_unexpected(SSL *s) | ||
487 | { | ||
488 | SSL3_RECORD_INTERNAL *rr = &s->s3->rrec; | ||
489 | int i; | ||
490 | |||
491 | if (s->internal->in_handshake) { | ||
492 | SSLerror(s, ERR_R_INTERNAL_ERROR); | ||
493 | return -1; | ||
494 | } | ||
495 | |||
496 | /* If we are a client, check for an incoming 'Hello Request': */ | ||
497 | if (!s->server && rr->type == SSL3_RT_HANDSHAKE && | ||
498 | rr->length >= DTLS1_HM_HEADER_LENGTH && rr->off == 0 && | ||
499 | rr->data[0] == SSL3_MT_HELLO_REQUEST && | ||
500 | s->session != NULL && s->session->cipher != NULL) { | ||
501 | struct hm_header_st msg_hdr; | ||
502 | CBS cbs; | ||
503 | |||
504 | CBS_init(&cbs, rr->data, rr->length); | ||
505 | if (!dtls1_get_message_header(&cbs, &msg_hdr)) | ||
506 | return -1; /* XXX - probably should drop/continue. */ | ||
507 | if (msg_hdr.msg_len != 0) { | ||
508 | SSLerror(s, SSL_R_BAD_HELLO_REQUEST); | ||
509 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | ||
510 | return -1; | ||
511 | } | ||
512 | rr->length = 0; | ||
513 | |||
514 | /* no need to check sequence number on HELLO REQUEST messages */ | ||
515 | |||
516 | ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, rr->data, 4); | ||
517 | |||
518 | if (SSL_is_init_finished(s) && | ||
519 | !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && | ||
520 | !s->s3->renegotiate) { | ||
521 | s->d1->handshake_read_seq++; | ||
522 | s->internal->new_session = 1; | ||
523 | ssl3_renegotiate(s); | ||
524 | if (ssl3_renegotiate_check(s)) { | ||
525 | i = s->internal->handshake_func(s); | ||
526 | if (i < 0) | ||
527 | return (i); | ||
528 | if (i == 0) { | ||
529 | SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); | ||
530 | return (-1); | ||
531 | } | ||
532 | |||
533 | if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { | ||
534 | if (s->s3->rbuf.left == 0) { | ||
535 | ssl_force_want_read(s); | ||
536 | return (-1); | ||
537 | } | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | /* we either finished a handshake or ignored the request, | ||
542 | * now try again to obtain the (application) data we were asked for */ | ||
543 | rr->length = 0; | ||
544 | return 1; | ||
545 | } | ||
546 | |||
547 | /* Unexpected handshake message (Client Hello, or protocol violation) */ | ||
548 | if (rr->type == SSL3_RT_HANDSHAKE && | ||
549 | rr->length >= DTLS1_HM_HEADER_LENGTH && rr->off == 0 && | ||
550 | !s->internal->in_handshake) { | ||
551 | struct hm_header_st msg_hdr; | ||
552 | CBS cbs; | ||
553 | |||
554 | /* this may just be a stale retransmit */ | ||
555 | CBS_init(&cbs, rr->data, rr->length); | ||
556 | if (!dtls1_get_message_header(&cbs, &msg_hdr)) | ||
557 | return -1; /* XXX - this should probably drop/continue. */ | ||
558 | if (rr->epoch != tls12_record_layer_read_epoch(s->internal->rl)) { | ||
559 | rr->length = 0; | ||
560 | return 1; | ||
561 | } | ||
562 | |||
563 | /* If we are server, we may have a repeated FINISHED of the | ||
564 | * client here, then retransmit our CCS and FINISHED. | ||
565 | */ | ||
566 | if (msg_hdr.type == SSL3_MT_FINISHED) { | ||
567 | if (dtls1_check_timeout_num(s) < 0) | ||
568 | return -1; | ||
569 | |||
570 | dtls1_retransmit_buffered_messages(s); | ||
571 | rr->length = 0; | ||
572 | return 1; | ||
573 | } | ||
574 | |||
575 | if (((s->s3->hs.state&SSL_ST_MASK) == SSL_ST_OK) && | ||
576 | !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { | ||
577 | s->s3->hs.state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; | ||
578 | s->internal->renegotiate = 1; | ||
579 | s->internal->new_session = 1; | ||
580 | } | ||
581 | i = s->internal->handshake_func(s); | ||
582 | if (i < 0) | ||
583 | return (i); | ||
584 | if (i == 0) { | ||
585 | SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); | ||
586 | return (-1); | ||
587 | } | ||
588 | |||
589 | if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { | ||
590 | if (s->s3->rbuf.left == 0) { | ||
591 | ssl_force_want_read(s); | ||
592 | return (-1); | ||
593 | } | ||
594 | } | ||
595 | rr->length = 0; | ||
596 | return 1; | ||
597 | } | ||
598 | |||
599 | return 1; | ||
600 | } | ||
601 | |||
485 | /* Return up to 'len' payload bytes received in 'type' records. | 602 | /* Return up to 'len' payload bytes received in 'type' records. |
486 | * 'type' is one of the following: | 603 | * 'type' is one of the following: |
487 | * | 604 | * |
@@ -684,57 +801,6 @@ dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
684 | } | 801 | } |
685 | } | 802 | } |
686 | 803 | ||
687 | /* If we are a client, check for an incoming 'Hello Request': */ | ||
688 | if (!s->server && rr->type == SSL3_RT_HANDSHAKE && | ||
689 | rr->length >= DTLS1_HM_HEADER_LENGTH && rr->off == 0 && | ||
690 | rr->data[0] == SSL3_MT_HELLO_REQUEST && | ||
691 | s->session != NULL && s->session->cipher != NULL) { | ||
692 | struct hm_header_st msg_hdr; | ||
693 | CBS cbs; | ||
694 | |||
695 | CBS_init(&cbs, rr->data, rr->length); | ||
696 | if (!dtls1_get_message_header(&cbs, &msg_hdr)) | ||
697 | return -1; | ||
698 | if (msg_hdr.msg_len != 0) { | ||
699 | al = SSL_AD_DECODE_ERROR; | ||
700 | SSLerror(s, SSL_R_BAD_HELLO_REQUEST); | ||
701 | goto fatal_err; | ||
702 | } | ||
703 | rr->length = 0; | ||
704 | |||
705 | /* no need to check sequence number on HELLO REQUEST messages */ | ||
706 | |||
707 | ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, rr->data, 4); | ||
708 | |||
709 | if (SSL_is_init_finished(s) && | ||
710 | !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && | ||
711 | !s->s3->renegotiate) { | ||
712 | s->d1->handshake_read_seq++; | ||
713 | s->internal->new_session = 1; | ||
714 | ssl3_renegotiate(s); | ||
715 | if (ssl3_renegotiate_check(s)) { | ||
716 | i = s->internal->handshake_func(s); | ||
717 | if (i < 0) | ||
718 | return (i); | ||
719 | if (i == 0) { | ||
720 | SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); | ||
721 | return (-1); | ||
722 | } | ||
723 | |||
724 | if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { | ||
725 | if (s->s3->rbuf.left == 0) { | ||
726 | ssl_force_want_read(s); | ||
727 | return (-1); | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | } | ||
732 | /* we either finished a handshake or ignored the request, | ||
733 | * now try again to obtain the (application) data we were asked for */ | ||
734 | rr->length = 0; | ||
735 | goto start; | ||
736 | } | ||
737 | |||
738 | if (rr->type == SSL3_RT_ALERT) { | 804 | if (rr->type == SSL3_RT_ALERT) { |
739 | if ((ret = ssl3_read_alert(s)) <= 0) | 805 | if ((ret = ssl3_read_alert(s)) <= 0) |
740 | return ret; | 806 | return ret; |
@@ -753,55 +819,9 @@ dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
753 | goto start; | 819 | goto start; |
754 | } | 820 | } |
755 | 821 | ||
756 | /* Unexpected handshake message (Client Hello, or protocol violation) */ | 822 | if (rr->type == SSL3_RT_HANDSHAKE) { |
757 | if (rr->type == SSL3_RT_HANDSHAKE && | 823 | if ((ret = dtls1_read_handshake_unexpected(s)) <= 0) |
758 | rr->length >= DTLS1_HM_HEADER_LENGTH && rr->off == 0 && | 824 | return ret; |
759 | !s->internal->in_handshake) { | ||
760 | struct hm_header_st msg_hdr; | ||
761 | CBS cbs; | ||
762 | |||
763 | /* this may just be a stale retransmit */ | ||
764 | CBS_init(&cbs, rr->data, rr->length); | ||
765 | if (!dtls1_get_message_header(&cbs, &msg_hdr)) | ||
766 | return -1; | ||
767 | if (rr->epoch != tls12_record_layer_read_epoch(s->internal->rl)) { | ||
768 | rr->length = 0; | ||
769 | goto start; | ||
770 | } | ||
771 | |||
772 | /* If we are server, we may have a repeated FINISHED of the | ||
773 | * client here, then retransmit our CCS and FINISHED. | ||
774 | */ | ||
775 | if (msg_hdr.type == SSL3_MT_FINISHED) { | ||
776 | if (dtls1_check_timeout_num(s) < 0) | ||
777 | return -1; | ||
778 | |||
779 | dtls1_retransmit_buffered_messages(s); | ||
780 | rr->length = 0; | ||
781 | goto start; | ||
782 | } | ||
783 | |||
784 | if (((s->s3->hs.state&SSL_ST_MASK) == SSL_ST_OK) && | ||
785 | !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { | ||
786 | s->s3->hs.state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; | ||
787 | s->internal->renegotiate = 1; | ||
788 | s->internal->new_session = 1; | ||
789 | } | ||
790 | i = s->internal->handshake_func(s); | ||
791 | if (i < 0) | ||
792 | return (i); | ||
793 | if (i == 0) { | ||
794 | SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); | ||
795 | return (-1); | ||
796 | } | ||
797 | |||
798 | if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { | ||
799 | if (s->s3->rbuf.left == 0) { | ||
800 | ssl_force_want_read(s); | ||
801 | return (-1); | ||
802 | } | ||
803 | } | ||
804 | rr->length = 0; | ||
805 | goto start; | 825 | goto start; |
806 | } | 826 | } |
807 | 827 | ||