* non blocking way, check if it is time to retransmit or just
* return.
*/
+
if (session->internals.dtls.flight_init != 0 && session->internals.dtls.blocking == 0)
{
/* just in case previous run was interrupted */
goto cleanup;
}
}
- else
- return ret;
}
-
do
{
if (now-session->internals.dtls.handshake_start_time >= session->internals.dtls.total_timeout_ms/1000)
session->internals.dtls.handshake_last_call = now;
session->internals.dtls.actual_retrans_timeout_ms = session->internals.dtls.retrans_timeout_ms;
- if (last_type == GNUTLS_HANDSHAKE_FINISHED && _dtls_is_async(session))
+ if (last_type == GNUTLS_HANDSHAKE_FINISHED)
{
/* we cannot do anything here. We just return 0 and
* if a retransmission occurs because peer didn't receive it
}
else
session->internals.dtls.last_flight = 0;
-
-
}
ret = _gnutls_io_write_flush (session);
return gnutls_assert_val(ret);
/* last message in handshake -> no ack */
- if (session->internals.dtls.last_flight != 0)
+ if (session->internals.dtls.last_flight != 0 && _dtls_is_async(session))
{
/* we cannot do anything here. We just return 0 and
* if a retransmission occurs because peer didn't receive it
int _dtls_record_check(gnutls_session_t session, uint64 * _seq)
{
uint64_t seq = 0, diff;
-int i, offset = 0;
+unsigned int i, offset = 0;
- for (i=0;i<8;i++)
+ seq |= _seq->i[0] & 0xff;
+ for (i=1;i<8;i++)
{
- seq |= _seq->i[i];
seq <<= 8;
+ seq |= _seq->i[i] & 0xff;
}
if (window_size == 0)
return -1;
}
- if (window_size == DTLS_RECORD_WINDOW_SIZE) {
- rot_window(session, MOVE_SIZE);
- }
+ if (window_size == DTLS_RECORD_WINDOW_SIZE)
+ {
+ rot_window(session, MOVE_SIZE);
+ }
if (seq < window_table[window_size-1])
{
if (diff >= window_size)
{
+ /* Probably an epoch change. Check if we can fit it */
+ if (window_table[0] == 0)
+ {
+ window_table[0] = seq;
+ return 0;
+ }
+
+ for (i=0;i<window_size-1;i++)
+ {
+ if (seq == window_table[i])
+ return -1;
+ if (seq == window_table[i] + 1)
+ {
+ if (seq == window_table[i+1])
+ return -1;
+ window_table[i+1] = seq;
+ return 0;
+ }
+ }
return -1;
}
offset = window_size-1-diff;
if (window_table[offset] == seq)
- {
- return -1;
- }
+ return -1;
else
- {
- window_table[offset] = seq;
- }
+ window_table[offset] = seq;
}
else /* seq >= last */
{
*/
if (IS_DTLS(session))
{
+ if (type == GNUTLS_CHANGE_CIPHER_SPEC)
+ {
+ ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
+ goto unexpected_packet;
+ }
+
if (_dtls_is_async(session) && _dtls_async_timer_active(session))
{
ret = _dtls_retransmit(session);
if (ret < 0)
{
gnutls_assert();
+ _gnutls_audit_log(session, "Discarded message[%u] due to invalid decryption\n",
+ (unsigned int)_gnutls_uint64touint32 (packet_sequence));
goto sanity_check_error;
}
ret = _dtls_record_check(session, packet_sequence);
if (ret < 0)
{
- _gnutls_audit_log(session, "Discarded duplicate message[%u]\n",
- (unsigned int) _gnutls_uint64touint32 (packet_sequence));
+ _gnutls_audit_log(session, "Discarded duplicate message[%u]: %s\n",
+ (unsigned int) _gnutls_uint64touint32 (packet_sequence), _gnutls_packet2str (record.type));
goto sanity_check_error;
}
}
if (IS_DTLS(session))
{
session->internals.dtls.packets_dropped++;
- _gnutls_audit_log(session, "Discarded message[%u] due to invalid decryption\n",
- (unsigned int)_gnutls_uint64touint32 (packet_sequence));
ret = gnutls_assert_val(GNUTLS_E_AGAIN);
goto cleanup;
}