tl;dr: I've been looking into an issue in my product (uses DTLS) for the
last couple of days. Tracked it down to a CHANGE_CIPHER_SPEC being
processed too early causing the handshake to never complete.

Details:

- OpenSSL version 1.0.1c
- Brackets indicate a single datagram packet.

(1) Client: send [SSL3_MT_CLIENT_HELLO]
(2) Server: send
[SSL3_MT_SERVER_HELLO, SSL3_MT_CERTIFICATE,
SSL3_MT_CERTIFICATE_REQUEST, SSL3_MT_SERVER_DONE]
(3) Client: send
[SSL3_MT_CERTIFICATE, SSL3_MT_CLIENT_KEY_EXCHANGE, SSL3_MT_CERTIFICATE_VERIFY,
*CHANGE_CIPHER*, SSL3_MT_FINISHED]

Client packet (3) is lost. Oh noes! Other stuff happens, but Client
eventually resends each message in its own datagram this time:

(4) Client: send [SSL3_MT_CERTIFICATE]
(5) Client: send [SSL3_MT_CLIENT_KEY_EXCHANGE]
(6) Client: send [SSL3_MT_CERTIFICATE_VERIFY]
(7) Client: send [*CHANGE_CIPHER*]
(8) Client: send [SSL3_MT_FINISHED]

Now, one of the following thing happens: a) packet (6) is lost or, in my
case, packet  (7) arrives before (6).

Unfortunately, when Server processes packet (7) it changes the cypher spec
before the handshake is over. When (6) finally arrives, it's dropped
by dtls1_read_bytes. Subsequent re-sends from Client are also ignored.

Without having read any spec, and with my limited knowledge of the OpenSSL
codebase, my naive interpretation is that the problem is caused by
dtls1_accept setting change_cipher_spec_ok on SSL3_ST_SR_CERT_VRFY_*
states.

Commenting out that line definitely seems to fix the problem for me. Is
this really the bug, or does that line plays a role in a different
scenario?

Cheers,
-dan

Reply via email to