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/ssl_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/ssl_pkt.c')
-rw-r--r-- | src/lib/libssl/ssl_pkt.c | 263 |
1 files changed, 135 insertions, 128 deletions
diff --git a/src/lib/libssl/ssl_pkt.c b/src/lib/libssl/ssl_pkt.c index 33bb4b659f..4dc7f3b610 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.55 2022/03/12 12:53:03 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_pkt.c,v 1.56 2022/03/14 16:49:35 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 | * |
@@ -814,6 +814,134 @@ ssl3_read_change_cipher_spec(SSL *s) | |||
814 | return 1; | 814 | return 1; |
815 | } | 815 | } |
816 | 816 | ||
817 | static int | ||
818 | ssl3_read_handshake_unexpected(SSL *s) | ||
819 | { | ||
820 | SSL3_RECORD_INTERNAL *rr = &s->s3->rrec; | ||
821 | int i; | ||
822 | |||
823 | /* | ||
824 | * We need four bytes of handshake data so we have a handshake message | ||
825 | * header - this may be in the same record or fragmented across multiple | ||
826 | * records. | ||
827 | */ | ||
828 | while (rr->length > 0 && | ||
829 | s->s3->handshake_fragment_len < sizeof(s->s3->handshake_fragment)) { | ||
830 | s->s3->handshake_fragment[s->s3->handshake_fragment_len++] = | ||
831 | rr->data[rr->off++]; | ||
832 | rr->length--; | ||
833 | } | ||
834 | |||
835 | if (s->s3->handshake_fragment_len < sizeof(s->s3->handshake_fragment)) | ||
836 | return 1; | ||
837 | |||
838 | if (s->internal->in_handshake) { | ||
839 | SSLerror(s, ERR_R_INTERNAL_ERROR); | ||
840 | return -1; | ||
841 | } | ||
842 | |||
843 | /* | ||
844 | * This code currently deals with HelloRequest and ClientHello messages - | ||
845 | * anything else is pushed to the handshake_func. Almost all of this | ||
846 | * belongs in the client/server handshake code. | ||
847 | */ | ||
848 | |||
849 | /* If we are a client, check for an incoming 'Hello Request': */ | ||
850 | if ((!s->server) && (s->s3->handshake_fragment_len >= 4) && | ||
851 | (s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) && | ||
852 | (s->session != NULL) && (s->session->cipher != NULL)) { | ||
853 | s->s3->handshake_fragment_len = 0; | ||
854 | |||
855 | if ((s->s3->handshake_fragment[1] != 0) || | ||
856 | (s->s3->handshake_fragment[2] != 0) || | ||
857 | (s->s3->handshake_fragment[3] != 0)) { | ||
858 | SSLerror(s, SSL_R_BAD_HELLO_REQUEST); | ||
859 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | ||
860 | return -1; | ||
861 | } | ||
862 | |||
863 | ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, | ||
864 | s->s3->handshake_fragment, 4); | ||
865 | |||
866 | if (SSL_is_init_finished(s) && | ||
867 | !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && | ||
868 | !s->s3->renegotiate) { | ||
869 | ssl3_renegotiate(s); | ||
870 | if (ssl3_renegotiate_check(s)) { | ||
871 | i = s->internal->handshake_func(s); | ||
872 | if (i < 0) | ||
873 | return (i); | ||
874 | if (i == 0) { | ||
875 | SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); | ||
876 | return (-1); | ||
877 | } | ||
878 | |||
879 | if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { | ||
880 | if (s->s3->rbuf.left == 0) { | ||
881 | ssl_force_want_read(s); | ||
882 | return (-1); | ||
883 | } | ||
884 | } | ||
885 | } | ||
886 | } | ||
887 | /* we either finished a handshake or ignored the request, | ||
888 | * now try again to obtain the (application) data we were asked for */ | ||
889 | return 1; | ||
890 | } | ||
891 | |||
892 | /* Disallow client initiated renegotiation if configured. */ | ||
893 | if (s->server && SSL_is_init_finished(s) && | ||
894 | s->s3->handshake_fragment_len >= 4 && | ||
895 | s->s3->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO && | ||
896 | (s->internal->options & SSL_OP_NO_CLIENT_RENEGOTIATION)) { | ||
897 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_NO_RENEGOTIATION); | ||
898 | return -1; | ||
899 | } | ||
900 | |||
901 | /* If we are a server and get a client hello when renegotiation isn't | ||
902 | * allowed send back a no renegotiation alert and carry on. | ||
903 | * WARNING: experimental code, needs reviewing (steve) | ||
904 | */ | ||
905 | if (s->server && | ||
906 | SSL_is_init_finished(s) && | ||
907 | !s->s3->send_connection_binding && | ||
908 | (s->s3->handshake_fragment_len >= 4) && | ||
909 | (s->s3->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) && | ||
910 | (s->session != NULL) && (s->session->cipher != NULL)) { | ||
911 | /*s->s3->handshake_fragment_len = 0;*/ | ||
912 | rr->length = 0; | ||
913 | ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); | ||
914 | return 1; | ||
915 | } | ||
916 | |||
917 | /* Unexpected handshake message (Client Hello, or protocol violation) */ | ||
918 | if ((s->s3->handshake_fragment_len >= 4) && !s->internal->in_handshake) { | ||
919 | if (((s->s3->hs.state&SSL_ST_MASK) == SSL_ST_OK) && | ||
920 | !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { | ||
921 | s->s3->hs.state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; | ||
922 | s->internal->renegotiate = 1; | ||
923 | s->internal->new_session = 1; | ||
924 | } | ||
925 | i = s->internal->handshake_func(s); | ||
926 | if (i < 0) | ||
927 | return (i); | ||
928 | if (i == 0) { | ||
929 | SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); | ||
930 | return (-1); | ||
931 | } | ||
932 | |||
933 | if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { | ||
934 | if (s->s3->rbuf.left == 0) { | ||
935 | ssl_force_want_read(s); | ||
936 | return (-1); | ||
937 | } | ||
938 | } | ||
939 | return 1; | ||
940 | } | ||
941 | |||
942 | return 1; | ||
943 | } | ||
944 | |||
817 | /* Return up to 'len' payload bytes received in 'type' records. | 945 | /* Return up to 'len' payload bytes received in 'type' records. |
818 | * 'type' is one of the following: | 946 | * 'type' is one of the following: |
819 | * | 947 | * |
@@ -950,7 +1078,6 @@ ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
950 | return (0); | 1078 | return (0); |
951 | } | 1079 | } |
952 | 1080 | ||
953 | |||
954 | /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ | 1081 | /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ |
955 | if (type == rr->type) { | 1082 | if (type == rr->type) { |
956 | /* make sure that we are not getting application data when we | 1083 | /* make sure that we are not getting application data when we |
@@ -986,111 +1113,10 @@ ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
986 | return (n); | 1113 | return (n); |
987 | } | 1114 | } |
988 | 1115 | ||
989 | 1116 | /* | |
990 | /* If we get here, then type != rr->type; if we have a handshake | 1117 | * If we get here, then type != rr->type; if we have a handshake |
991 | * message, then it was unexpected (Hello Request or Client Hello). */ | 1118 | * message, then it was unexpected (Hello Request or Client Hello). |
992 | |||
993 | { | ||
994 | /* | ||
995 | * In case of record types for which we have 'fragment' | ||
996 | * storage, * fill that so that we can process the data | ||
997 | * at a fixed place. | ||
998 | */ | ||
999 | unsigned int dest_maxlen = 0; | ||
1000 | unsigned char *dest = NULL; | ||
1001 | unsigned int *dest_len = NULL; | ||
1002 | |||
1003 | if (rr->type == SSL3_RT_HANDSHAKE) { | ||
1004 | dest_maxlen = sizeof s->s3->handshake_fragment; | ||
1005 | dest = s->s3->handshake_fragment; | ||
1006 | dest_len = &s->s3->handshake_fragment_len; | ||
1007 | } | ||
1008 | if (dest_maxlen > 0) { | ||
1009 | /* available space in 'dest' */ | ||
1010 | n = dest_maxlen - *dest_len; | ||
1011 | if (rr->length < n) | ||
1012 | n = rr->length; /* available bytes */ | ||
1013 | |||
1014 | /* now move 'n' bytes: */ | ||
1015 | while (n-- > 0) { | ||
1016 | dest[(*dest_len)++] = rr->data[rr->off++]; | ||
1017 | rr->length--; | ||
1018 | } | ||
1019 | |||
1020 | if (*dest_len < dest_maxlen) | ||
1021 | goto start; /* fragment was too small */ | ||
1022 | } | ||
1023 | } | ||
1024 | |||
1025 | /* s->s3->handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE; | ||
1026 | * s->s3->alert_fragment_len == 2 iff rr->type == SSL3_RT_ALERT. | ||
1027 | * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */ | ||
1028 | |||
1029 | /* If we are a client, check for an incoming 'Hello Request': */ | ||
1030 | if ((!s->server) && (s->s3->handshake_fragment_len >= 4) && | ||
1031 | (s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) && | ||
1032 | (s->session != NULL) && (s->session->cipher != NULL)) { | ||
1033 | s->s3->handshake_fragment_len = 0; | ||
1034 | |||
1035 | if ((s->s3->handshake_fragment[1] != 0) || | ||
1036 | (s->s3->handshake_fragment[2] != 0) || | ||
1037 | (s->s3->handshake_fragment[3] != 0)) { | ||
1038 | al = SSL_AD_DECODE_ERROR; | ||
1039 | SSLerror(s, SSL_R_BAD_HELLO_REQUEST); | ||
1040 | goto fatal_err; | ||
1041 | } | ||
1042 | |||
1043 | ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, | ||
1044 | s->s3->handshake_fragment, 4); | ||
1045 | |||
1046 | if (SSL_is_init_finished(s) && | ||
1047 | !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) && | ||
1048 | !s->s3->renegotiate) { | ||
1049 | ssl3_renegotiate(s); | ||
1050 | if (ssl3_renegotiate_check(s)) { | ||
1051 | i = s->internal->handshake_func(s); | ||
1052 | if (i < 0) | ||
1053 | return (i); | ||
1054 | if (i == 0) { | ||
1055 | SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); | ||
1056 | return (-1); | ||
1057 | } | ||
1058 | |||
1059 | if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { | ||
1060 | if (s->s3->rbuf.left == 0) { | ||
1061 | ssl_force_want_read(s); | ||
1062 | return (-1); | ||
1063 | } | ||
1064 | } | ||
1065 | } | ||
1066 | } | ||
1067 | /* we either finished a handshake or ignored the request, | ||
1068 | * now try again to obtain the (application) data we were asked for */ | ||
1069 | goto start; | ||
1070 | } | ||
1071 | /* Disallow client initiated renegotiation if configured. */ | ||
1072 | if (s->server && SSL_is_init_finished(s) && | ||
1073 | s->s3->handshake_fragment_len >= 4 && | ||
1074 | s->s3->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO && | ||
1075 | (s->internal->options & SSL_OP_NO_CLIENT_RENEGOTIATION)) { | ||
1076 | al = SSL_AD_NO_RENEGOTIATION; | ||
1077 | goto fatal_err; | ||
1078 | } | ||
1079 | /* If we are a server and get a client hello when renegotiation isn't | ||
1080 | * allowed send back a no renegotiation alert and carry on. | ||
1081 | * WARNING: experimental code, needs reviewing (steve) | ||
1082 | */ | 1119 | */ |
1083 | if (s->server && | ||
1084 | SSL_is_init_finished(s) && | ||
1085 | !s->s3->send_connection_binding && | ||
1086 | (s->s3->handshake_fragment_len >= 4) && | ||
1087 | (s->s3->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) && | ||
1088 | (s->session != NULL) && (s->session->cipher != NULL)) { | ||
1089 | /*s->s3->handshake_fragment_len = 0;*/ | ||
1090 | rr->length = 0; | ||
1091 | ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); | ||
1092 | goto start; | ||
1093 | } | ||
1094 | 1120 | ||
1095 | if (rr->type == SSL3_RT_ALERT) { | 1121 | if (rr->type == SSL3_RT_ALERT) { |
1096 | if ((ret = ssl3_read_alert(s)) <= 0) | 1122 | if ((ret = ssl3_read_alert(s)) <= 0) |
@@ -1111,28 +1137,9 @@ ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) | |||
1111 | goto start; | 1137 | goto start; |
1112 | } | 1138 | } |
1113 | 1139 | ||
1114 | /* Unexpected handshake message (Client Hello, or protocol violation) */ | 1140 | if (rr->type == SSL3_RT_HANDSHAKE) { |
1115 | if ((s->s3->handshake_fragment_len >= 4) && !s->internal->in_handshake) { | 1141 | if ((ret = ssl3_read_handshake_unexpected(s)) <= 0) |
1116 | if (((s->s3->hs.state&SSL_ST_MASK) == SSL_ST_OK) && | 1142 | return ret; |
1117 | !(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)) { | ||
1118 | s->s3->hs.state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; | ||
1119 | s->internal->renegotiate = 1; | ||
1120 | s->internal->new_session = 1; | ||
1121 | } | ||
1122 | i = s->internal->handshake_func(s); | ||
1123 | if (i < 0) | ||
1124 | return (i); | ||
1125 | if (i == 0) { | ||
1126 | SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); | ||
1127 | return (-1); | ||
1128 | } | ||
1129 | |||
1130 | if (!(s->internal->mode & SSL_MODE_AUTO_RETRY)) { | ||
1131 | if (s->s3->rbuf.left == 0) { | ||
1132 | ssl_force_want_read(s); | ||
1133 | return (-1); | ||
1134 | } | ||
1135 | } | ||
1136 | goto start; | 1143 | goto start; |
1137 | } | 1144 | } |
1138 | 1145 | ||