diff options
author | jsing <> | 2022-02-21 18:22:20 +0000 |
---|---|---|
committer | jsing <> | 2022-02-21 18:22:20 +0000 |
commit | a59b14b2d3f8047fe5b687d37304433773603a3f (patch) | |
tree | b58aa2f628b6d8b36920b544c96c0647c2281969 /src/lib | |
parent | 194ce8d94cd74f12663cf8ca258294804ca1aabf (diff) | |
download | openbsd-a59b14b2d3f8047fe5b687d37304433773603a3f.tar.gz openbsd-a59b14b2d3f8047fe5b687d37304433773603a3f.tar.bz2 openbsd-a59b14b2d3f8047fe5b687d37304433773603a3f.zip |
Factor out alert handing code in the legacy stack.libressl-v3.5.0
Pull out the code that processes incoming alerts - a chunk of the
complexity is due to the fact that in TLSv1.2 and earlier, alerts can be
fragmented across multiple records or multiple alerts can be delivered
in a single record.
In DTLS there is no way that we can reassemble fragmented alerts (although
the RFC is silent on this), however we could have multiple alerts in the
same record. This change means that we will handle this situation more
appropriately and if we encounter a fragmented alert we will now treat this
as a decode error (instead of silently ignoring it).
ok beck@ tb@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libssl/d1_pkt.c | 37 | ||||
-rw-r--r-- | src/lib/libssl/ssl_locl.h | 3 | ||||
-rw-r--r-- | src/lib/libssl/ssl_pkt.c | 122 |
3 files changed, 77 insertions, 85 deletions
diff --git a/src/lib/libssl/d1_pkt.c b/src/lib/libssl/d1_pkt.c index e884f2d592..e07fc7e3f9 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.117 2022/02/05 14:54:10 jsing Exp $ */ | 1 | /* $OpenBSD: d1_pkt.c,v 1.118 2022/02/21 18:22:20 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. |
@@ -735,38 +735,9 @@ dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
735 | goto start; | 735 | goto start; |
736 | } | 736 | } |
737 | 737 | ||
738 | if (rr->type == SSL3_RT_ALERT && rr->length >= DTLS1_AL_HEADER_LENGTH && | 738 | if (rr->type == SSL3_RT_ALERT) { |
739 | rr->off == 0) { | 739 | if ((ret = ssl3_read_alert(s)) <= 0) |
740 | int alert_level = rr->data[0]; | 740 | return ret; |
741 | int alert_descr = rr->data[1]; | ||
742 | |||
743 | ssl_msg_callback(s, 0, SSL3_RT_ALERT, rr->data, 2); | ||
744 | |||
745 | ssl_info_callback(s, SSL_CB_READ_ALERT, | ||
746 | (alert_level << 8) | alert_descr); | ||
747 | |||
748 | if (alert_level == SSL3_AL_WARNING) { | ||
749 | s->s3->warn_alert = alert_descr; | ||
750 | if (alert_descr == SSL_AD_CLOSE_NOTIFY) { | ||
751 | s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; | ||
752 | return (0); | ||
753 | } | ||
754 | } else if (alert_level == SSL3_AL_FATAL) { | ||
755 | s->internal->rwstate = SSL_NOTHING; | ||
756 | s->s3->fatal_alert = alert_descr; | ||
757 | SSLerror(s, SSL_AD_REASON_OFFSET + alert_descr); | ||
758 | ERR_asprintf_error_data("SSL alert number %d", | ||
759 | alert_descr); | ||
760 | s->internal->shutdown|=SSL_RECEIVED_SHUTDOWN; | ||
761 | SSL_CTX_remove_session(s->ctx, s->session); | ||
762 | return (0); | ||
763 | } else { | ||
764 | al = SSL_AD_ILLEGAL_PARAMETER; | ||
765 | SSLerror(s, SSL_R_UNKNOWN_ALERT_TYPE); | ||
766 | goto fatal_err; | ||
767 | } | ||
768 | |||
769 | rr->length = 0; | ||
770 | goto start; | 741 | goto start; |
771 | } | 742 | } |
772 | 743 | ||
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index 69e52dcc8c..ada99494db 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_locl.h,v 1.385 2022/02/05 14:54:10 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_locl.h,v 1.386 2022/02/21 18:22:20 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -1333,6 +1333,7 @@ int ssl3_renegotiate_check(SSL *ssl); | |||
1333 | void ssl_force_want_read(SSL *s); | 1333 | void ssl_force_want_read(SSL *s); |
1334 | 1334 | ||
1335 | int ssl3_dispatch_alert(SSL *s); | 1335 | int ssl3_dispatch_alert(SSL *s); |
1336 | int ssl3_read_alert(SSL *s); | ||
1336 | int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); | 1337 | int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); |
1337 | int ssl3_write_bytes(SSL *s, int type, const void *buf, int len); | 1338 | int ssl3_write_bytes(SSL *s, int type, const void *buf, int len); |
1338 | int ssl3_output_cert_chain(SSL *s, CBB *cbb, SSL_CERT_PKEY *cpk); | 1339 | int ssl3_output_cert_chain(SSL *s, CBB *cbb, SSL_CERT_PKEY *cpk); |
diff --git a/src/lib/libssl/ssl_pkt.c b/src/lib/libssl/ssl_pkt.c index 3374713644..e3b2034eb4 100644 --- a/src/lib/libssl/ssl_pkt.c +++ b/src/lib/libssl/ssl_pkt.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_pkt.c,v 1.53 2022/02/05 14:54:10 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_pkt.c,v 1.54 2022/02/21 18:22:20 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -685,6 +685,73 @@ ssl3_write_pending(SSL *s, int type, const unsigned char *buf, unsigned int len) | |||
685 | } | 685 | } |
686 | } | 686 | } |
687 | 687 | ||
688 | int | ||
689 | ssl3_read_alert(SSL *s) | ||
690 | { | ||
691 | SSL3_RECORD_INTERNAL *rr = &s->s3->rrec; | ||
692 | uint8_t alert_level, alert_descr; | ||
693 | |||
694 | /* | ||
695 | * TLSv1.2 permits an alert to be fragmented across multiple records or | ||
696 | * for multiple alerts to be be coalesced into a single alert record. | ||
697 | * In the case of DTLS, there is no way to reassemble an alert | ||
698 | * fragmented across multiple records, hence a full alert must be | ||
699 | * available in the record. | ||
700 | */ | ||
701 | while (rr->length > 0 && | ||
702 | s->s3->alert_fragment_len < sizeof(s->s3->alert_fragment)) { | ||
703 | s->s3->alert_fragment[s->s3->alert_fragment_len++] = | ||
704 | rr->data[rr->off++]; | ||
705 | rr->length--; | ||
706 | } | ||
707 | if (s->s3->alert_fragment_len < sizeof(s->s3->alert_fragment)) { | ||
708 | if (SSL_is_dtls(s)) { | ||
709 | SSLerror(s, SSL_R_BAD_LENGTH); | ||
710 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | ||
711 | return -1; | ||
712 | } | ||
713 | return 1; | ||
714 | } | ||
715 | |||
716 | ssl_msg_callback(s, 0, SSL3_RT_ALERT, s->s3->alert_fragment, 2); | ||
717 | |||
718 | alert_level = s->s3->alert_fragment[0]; | ||
719 | alert_descr = s->s3->alert_fragment[1]; | ||
720 | s->s3->alert_fragment_len = 0; | ||
721 | |||
722 | ssl_info_callback(s, SSL_CB_READ_ALERT, | ||
723 | (alert_level << 8) | alert_descr); | ||
724 | |||
725 | if (alert_level == SSL3_AL_WARNING) { | ||
726 | s->s3->warn_alert = alert_descr; | ||
727 | if (alert_descr == SSL_AD_CLOSE_NOTIFY) { | ||
728 | s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; | ||
729 | return 0; | ||
730 | } | ||
731 | /* We requested renegotiation and the peer rejected it. */ | ||
732 | if (alert_descr == SSL_AD_NO_RENEGOTIATION) { | ||
733 | SSLerror(s, SSL_R_NO_RENEGOTIATION); | ||
734 | ssl3_send_alert(s, SSL3_AL_FATAL, | ||
735 | SSL_AD_HANDSHAKE_FAILURE); | ||
736 | return -1; | ||
737 | } | ||
738 | } else if (alert_level == SSL3_AL_FATAL) { | ||
739 | s->internal->rwstate = SSL_NOTHING; | ||
740 | s->s3->fatal_alert = alert_descr; | ||
741 | SSLerror(s, SSL_AD_REASON_OFFSET + alert_descr); | ||
742 | ERR_asprintf_error_data("SSL alert number %d", alert_descr); | ||
743 | s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; | ||
744 | SSL_CTX_remove_session(s->ctx, s->session); | ||
745 | return 0; | ||
746 | } else { | ||
747 | SSLerror(s, SSL_R_UNKNOWN_ALERT_TYPE); | ||
748 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); | ||
749 | return -1; | ||
750 | } | ||
751 | |||
752 | return 1; | ||
753 | } | ||
754 | |||
688 | /* Return up to 'len' payload bytes received in 'type' records. | 755 | /* Return up to 'len' payload bytes received in 'type' records. |
689 | * 'type' is one of the following: | 756 | * 'type' is one of the following: |
690 | * | 757 | * |
@@ -875,10 +942,6 @@ ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
875 | dest_maxlen = sizeof s->s3->handshake_fragment; | 942 | dest_maxlen = sizeof s->s3->handshake_fragment; |
876 | dest = s->s3->handshake_fragment; | 943 | dest = s->s3->handshake_fragment; |
877 | dest_len = &s->s3->handshake_fragment_len; | 944 | dest_len = &s->s3->handshake_fragment_len; |
878 | } else if (rr->type == SSL3_RT_ALERT) { | ||
879 | dest_maxlen = sizeof s->s3->alert_fragment; | ||
880 | dest = s->s3->alert_fragment; | ||
881 | dest_len = &s->s3->alert_fragment_len; | ||
882 | } | 945 | } |
883 | if (dest_maxlen > 0) { | 946 | if (dest_maxlen > 0) { |
884 | /* available space in 'dest' */ | 947 | /* available space in 'dest' */ |
@@ -966,53 +1029,10 @@ ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
966 | ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); | 1029 | ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); |
967 | goto start; | 1030 | goto start; |
968 | } | 1031 | } |
969 | if (s->s3->alert_fragment_len >= 2) { | ||
970 | int alert_level = s->s3->alert_fragment[0]; | ||
971 | int alert_descr = s->s3->alert_fragment[1]; | ||
972 | |||
973 | s->s3->alert_fragment_len = 0; | ||
974 | |||
975 | ssl_msg_callback(s, 0, SSL3_RT_ALERT, | ||
976 | s->s3->alert_fragment, 2); | ||
977 | |||
978 | ssl_info_callback(s, SSL_CB_READ_ALERT, | ||
979 | (alert_level << 8) | alert_descr); | ||
980 | |||
981 | if (alert_level == SSL3_AL_WARNING) { | ||
982 | s->s3->warn_alert = alert_descr; | ||
983 | if (alert_descr == SSL_AD_CLOSE_NOTIFY) { | ||
984 | s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; | ||
985 | return (0); | ||
986 | } | ||
987 | /* This is a warning but we receive it if we requested | ||
988 | * renegotiation and the peer denied it. Terminate with | ||
989 | * a fatal alert because if application tried to | ||
990 | * renegotiatie it presumably had a good reason and | ||
991 | * expects it to succeed. | ||
992 | * | ||
993 | * In future we might have a renegotiation where we | ||
994 | * don't care if the peer refused it where we carry on. | ||
995 | */ | ||
996 | else if (alert_descr == SSL_AD_NO_RENEGOTIATION) { | ||
997 | al = SSL_AD_HANDSHAKE_FAILURE; | ||
998 | SSLerror(s, SSL_R_NO_RENEGOTIATION); | ||
999 | goto fatal_err; | ||
1000 | } | ||
1001 | } else if (alert_level == SSL3_AL_FATAL) { | ||
1002 | s->internal->rwstate = SSL_NOTHING; | ||
1003 | s->s3->fatal_alert = alert_descr; | ||
1004 | SSLerror(s, SSL_AD_REASON_OFFSET + alert_descr); | ||
1005 | ERR_asprintf_error_data("SSL alert number %d", | ||
1006 | alert_descr); | ||
1007 | s->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; | ||
1008 | SSL_CTX_remove_session(s->ctx, s->session); | ||
1009 | return (0); | ||
1010 | } else { | ||
1011 | al = SSL_AD_ILLEGAL_PARAMETER; | ||
1012 | SSLerror(s, SSL_R_UNKNOWN_ALERT_TYPE); | ||
1013 | goto fatal_err; | ||
1014 | } | ||
1015 | 1032 | ||
1033 | if (rr->type == SSL3_RT_ALERT) { | ||
1034 | if ((ret = ssl3_read_alert(s)) <= 0) | ||
1035 | return ret; | ||
1016 | goto start; | 1036 | goto start; |
1017 | } | 1037 | } |
1018 | 1038 | ||