openssl icon indicating copy to clipboard operation
openssl copied to clipboard

Dtls over udp, the sum of fragment_offset and fragment_length exceeds the total handshake message length

Open hddfg opened this issue 1 year ago • 11 comments

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.

hddfg avatar Sep 02 '24 13:09 hddfg

Is this issue present with the 3.0.14 and 3.3.1 versions? Could you please test against these versions?

t8m avatar Sep 02 '24 15:09 t8m

I tested 3.0.14 and 3.3.1 and both had the same problem.

hddfg avatar Sep 03 '24 07:09 hddfg

@mattcaswell could perhaps look at this?

t8m avatar Sep 03 '24 07:09 t8m

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.

vdukhovni avatar Sep 03 '24 12:09 vdukhovni

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.

hddfg avatar Sep 03 '24 13:09 hddfg

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

hddfg avatar Sep 03 '24 13:09 hddfg

@mattcaswell ping

nhorman avatar Oct 03 '24 08:10 nhorman

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.

mattcaswell avatar Oct 03 '24 08:10 mattcaswell

Given the comment from @mattcaswell, it looks like this issue should be closed (perhaps after the follow-on isssue is opened and linked here).

vdukhovni avatar Oct 10 '24 07:10 vdukhovni

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.

hddfg avatar Oct 10 '24 13:10 hddfg

@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

hddfg avatar Oct 15 '24 11:10 hddfg