Dtls over udp, the sum of fragment_offset and fragment_length exceeds the total handshake message length
version: 3.0.9
Description
In the Dtls over udp scenario, I construct an abnormal handshake packet which the sum of fragment_offset and fragment_length exceeds the total handshake message length, but the peer doesn't send alert. After debugging, I found that it returned 0 when dtls1_reassemble_fragment statem_dtls.c:611 failed. The error code obtained by using SSL_get_error is SSL_ERROR_WANT_READ. Therefore, let peer invoked SSL_connect again. The peer end continued to parse the remaining packet content as a new DTLS handshake header, and the parse process failed.
Question
1.Why doesn't send an alert when the sum of fragment_offset and fragment_length exceeds the total handshake message length? The same consideration also exits in function dtls1_process_out_of_seq_message statem_dtls.c:719.
2.When a packet with incorrect fragment_offset and fragment_length is discared, why doesn't clear its content?
Code
https://github.com/openssl/openssl/blob/de90e54bbe82e5be4fb9608b6f5c308bb837d355/ssl/statem/statem_dtls.c#L599-L706
I look forward to hearing from you. Thanks.
Is this issue present with the 3.0.14 and 3.3.1 versions? Could you please test against these versions?
I tested 3.0.14 and 3.3.1 and both had the same problem.
@mattcaswell could perhaps look at this?
It is not clear to me that simply ignoring the invalid fragment is not correct behaviour. Isn't that what one might expect in light of https://datatracker.ietf.org/doc/html/rfc6347#section-4.1.2.1 and https://datatracker.ietf.org/doc/html/rfc6347#section-4.1.2.7?
Alert messages can after all be lost. The sending application SHOULD NOT send invalid records.
For your reply, I agree to ignore the invalid fragment, but after ignoring it, I continue to call SSL_connect to read the rest of fragments, but actually the body of the first invalid fragment is not ignored, it still exists in the read buffer. So openssl regards it as the header of the rest of fragments, which cause to parse error.
In another scenario, when the function dtls1_process_out_of_seq_message statem_dtls.c:719 returns a failure, the error code obtained by using SSL_get_error is SSL_ERROR_SYSCALL. Generally, the message is ignored. However, the error code is incorrect and we cannot continue handshake by calling SSL_connect again. SSL_connect can be called again to establish a link only when the error code is SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.
https://github.com/openssl/openssl/blob/de90e54bbe82e5be4fb9608b6f5c308bb837d355/ssl/statem/statem_dtls.c#L708-L804
@mattcaswell ping
It is not clear to me that simply ignoring the invalid fragment is not correct behaviour. Isn't that what one might expect in light of https://datatracker.ietf.org/doc/html/rfc6347#section-4.1.2.1 and https://datatracker.ietf.org/doc/html/rfc6347#section-4.1.2.7?
Alert messages can after all be lost. The sending application SHOULD NOT send invalid records.
Right. IMO @vdukhovni is correct here and not sending an alert is the right behaviour according to the RFC.
For your reply, I agree to ignore the invalid fragment, but after ignoring it, I continue to call SSL_connect to read the rest of fragments, but actually the body of the first invalid fragment is not ignored, it still exists in the read buffer. So openssl regards it as the header of the rest of fragments, which cause to parse error.
The RFC says nothing about clearing the content from earlier received records which were successfully parsed and processed. So this also seems correct behaviour.
In another scenario, when the function dtls1_process_out_of_seq_message statem_dtls.c:719 returns a failure, the error code obtained by using SSL_get_error is SSL_ERROR_SYSCALL. Generally, the message is ignored. However, the error code is incorrect and we cannot continue handshake by calling SSL_connect again. SSL_connect can be called again to establish a link only when the error code is SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.
Please raise this as a separate issue.
Given the comment from @mattcaswell, it looks like this issue should be closed (perhaps after the follow-on isssue is opened and linked here).
It is not clear to me that simply ignoring the invalid fragment is not correct behaviour. Isn't that what one might expect in light of https://datatracker.ietf.org/doc/html/rfc6347#section-4.1.2.1 and https://datatracker.ietf.org/doc/html/rfc6347#section-4.1.2.7? Alert messages can after all be lost. The sending application SHOULD NOT send invalid records.
Right. IMO @vdukhovni is correct here and not sending an alert is the right behaviour according to the RFC.
For your reply, I agree to ignore the invalid fragment, but after ignoring it, I continue to call SSL_connect to read the rest of fragments, but actually the body of the first invalid fragment is not ignored, it still exists in the read buffer. So openssl regards it as the header of the rest of fragments, which cause to parse error.
The RFC says nothing about clearing the content from earlier received records which were successfully parsed and processed. So this also seems correct behaviour.
In another scenario, when the function dtls1_process_out_of_seq_message statem_dtls.c:719 returns a failure, the error code obtained by using SSL_get_error is SSL_ERROR_SYSCALL. Generally, the message is ignored. However, the error code is incorrect and we cannot continue handshake by calling SSL_connect again. SSL_connect can be called again to establish a link only when the error code is SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.
Please raise this as a separate issue.
Okay, I got it.
@mattcaswell
In another scenario, when the function dtls1_process_out_of_seq_message statem_dtls.c:719 returns a failure, the error code obtained by using SSL_get_error is SSL_ERROR_SYSCALL. Generally, the message is ignored. However, the error code is incorrect and we cannot continue handshake by calling SSL_connect again. SSL_connect can be called again to establish a link only when the error code is SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.
Please raise this as a separate issue.
Hello, the new issue is here. https://github.com/openssl/openssl/issues/25698