Ejemplo n.º 1
0
static void check_dtls_window_epoch_higher(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;

	RESET_WINDOW;
	SET_WINDOW_NEXT(LARGE_INT-1);
	SET_WINDOW_LAST_RECV(LARGE_INT);

	uint64_set(&t, BSWAP64(LARGE_INT));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64((LARGE_INT+8)|0x1000000000000LL));
	assert_int_equal(_dtls_record_check(&state, &t), -1);
}
Ejemplo n.º 2
0
static void check_dtls_window_uninit_large(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;

	RESET_WINDOW;

	uint64_set(&t, BSWAP64(LARGE_INT+1+64));

	assert_int_equal(_dtls_record_check(&state, &t), 0);
}
Ejemplo n.º 3
0
static void check_dtls_window_uninit_very_large(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;

	RESET_WINDOW;

	uint64_set(&t, BSWAP64(INT_OVER_32_BITS));

	assert_int_equal(_dtls_record_check(&state, &t), 0);
}
Ejemplo n.º 4
0
static void check_dtls_window_uninit_0(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;

	RESET_WINDOW;
	SET_WINDOW_NEXT(0);

	uint64_set(&t, 0);

	assert_int_equal(_dtls_record_check(&state, &t), 0);
}
Ejemplo n.º 5
0
static void check_dtls_window_epoch_lower(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;

	RESET_WINDOW;
	uint64_set(&t, BSWAP64(0x1000000000000LL));

	state.epoch = 1;
	SET_WINDOW_NEXT(0x1000000000000LL);
	SET_WINDOW_LAST_RECV((0x1000000000000LL) + 1);

	uint64_set(&t, BSWAP64(2 | 0x1000000000000LL));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(3 | 0x1000000000000LL));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(5));
	assert_int_equal(_dtls_record_check(&state, &t), -1);
}
Ejemplo n.º 6
0
static void check_dtls_window_dup3(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;

	RESET_WINDOW;
	SET_WINDOW_NEXT(LARGE_INT-1);
	SET_WINDOW_LAST_RECV(LARGE_INT);

	uint64_set(&t, BSWAP64(LARGE_INT));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+16));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+15));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+14));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+5));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+5));
	assert_int_equal(_dtls_record_check(&state, &t), -3);
}
Ejemplo n.º 7
0
static void check_dtls_window_out_of_order(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;

	RESET_WINDOW;
	SET_WINDOW_NEXT(LARGE_INT-1);
	SET_WINDOW_LAST_RECV(LARGE_INT);

	uint64_set(&t, BSWAP64(LARGE_INT));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+8));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+7));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+6));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+5));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+4));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+3));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+2));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+1));
	assert_int_equal(_dtls_record_check(&state, &t), 0);

	uint64_set(&t, BSWAP64(LARGE_INT+9));
	assert_int_equal(_dtls_record_check(&state, &t), 0);
}
Ejemplo n.º 8
0
static void check_dtls_window_very_large_outside(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;

	RESET_WINDOW;
	SET_WINDOW_NEXT(INT_OVER_32_BITS);
	SET_WINDOW_LAST_RECV(INT_OVER_32_BITS+1);

	uint64_set(&t, BSWAP64(INT_OVER_32_BITS+1+64));

	assert_int_equal(_dtls_record_check(&state, &t), 0);
}
Ejemplo n.º 9
0
static void check_dtls_window_91(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;

	RESET_WINDOW;
	SET_WINDOW_NEXT(0);
	SET_WINDOW_LAST_RECV(9);

	uint64_set(&t, BSWAP64(1));

	assert_int_equal(_dtls_record_check(&state, &t), 0);
}
Ejemplo n.º 10
0
static void check_dtls_window_skip3(void **glob_state)
{
	struct record_parameters_st state;
	uint64 t;
	unsigned i;

	RESET_WINDOW;
	SET_WINDOW_NEXT(0);
	SET_WINDOW_LAST_RECV(1);

	for (i=5;i<256;i+=2) {
		uint64_set(&t, BSWAP64(i));
		assert_int_equal(_dtls_record_check(&state, &t), 0);
	}
}
Ejemplo n.º 11
0
/* @ms: is the number of milliseconds to wait for data. Use zero for indefinite.
 *
 * This will receive record layer packets and add them to 
 * application_data_buffer and handshake_data_buffer.
 *
 * If the htype is not -1 then handshake timeouts
 * will be enforced.
 */
ssize_t
_gnutls_recv_in_buffers (gnutls_session_t session, content_type_t type,
                         gnutls_handshake_description_t htype, unsigned int ms)
{
  uint64 *packet_sequence;
  gnutls_datum_t ciphertext;
  mbuffer_st* bufel = NULL, *decrypted = NULL;
  gnutls_datum_t t;
  int ret;
  unsigned int empty_fragments = 0;
  record_parameters_st *record_params;
  record_state_st *record_state;
  struct tls_record_st record;

begin:

  if (empty_fragments > session->internals.priorities.max_empty_records)
    {
      gnutls_assert ();
      return GNUTLS_E_TOO_MANY_EMPTY_PACKETS;
    }

  if (session->internals.read_eof != 0)
    {
      /* if we have already read an EOF
       */
      return 0;
    }
  else if (session_is_valid (session) != 0
           || session->internals.may_not_read != 0)
    return gnutls_assert_val(GNUTLS_E_INVALID_SESSION);

  /* get the record state parameters */
  ret = _gnutls_epoch_get (session, EPOCH_READ_CURRENT, &record_params);
  if (ret < 0)
    return gnutls_assert_val (ret);

  /* Safeguard against processing data with an incomplete cipher state. */
  if (!record_params->initialized)
    return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);

  record_state = &record_params->read;

  /* receive headers */
  ret = recv_headers(session, type, htype, &record, &ms);
  if (ret < 0)
    {
      ret = gnutls_assert_val_fatal(ret);
      goto recv_error;
    }

  if (IS_DTLS(session)) 
    packet_sequence = &record.sequence;
  else
    packet_sequence = &record_state->sequence_number;

  /* Read the packet data and insert it to record_recv_buffer.
   */
  ret =
       _gnutls_io_read_buffered (session, record.packet_size,
                                 record.type, &ms);
  if (ret != record.packet_size)
    {
      gnutls_assert();
      goto recv_error;
    }

  /* ok now we are sure that we have read all the data - so
   * move on !
   */
  ret = _mbuffer_linearize (&session->internals.record_recv_buffer);
  if (ret < 0)
    return gnutls_assert_val(ret);

  bufel = _mbuffer_head_get_first (&session->internals.record_recv_buffer, NULL);
  if (bufel == NULL)
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

  /* We allocate the maximum possible to allow few compressed bytes to expand to a
   * full record.
   */
  decrypted = _mbuffer_alloc(record.length, record.length);
  if (decrypted == NULL)
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

  ciphertext.data = (uint8_t*)_mbuffer_get_udata_ptr(bufel) + record.header_size;
  ciphertext.size = record.length;

  /* decrypt the data we got. 
   */
  t.data = _mbuffer_get_udata_ptr(decrypted);
  t.size = _mbuffer_get_udata_size(decrypted);
  ret =
    _gnutls_decrypt (session, &ciphertext, &t,
		     record.type, record_params, packet_sequence);
  if (ret >= 0) _mbuffer_set_udata_size(decrypted, ret);

  _mbuffer_head_remove_bytes (&session->internals.record_recv_buffer,
                              record.header_size + record.length);
  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;
    }

  /* check for duplicates. We check after the message
   * is processed and authenticated to avoid someone
   * messing with our windows.
   */
  if (IS_DTLS(session) && session->internals.no_replay_protection == 0)
    {
      ret = _dtls_record_check(record_params, packet_sequence);
      if (ret < 0)
        {
          _gnutls_audit_log(session, "Discarded duplicate message[%u.%u]: %s\n",
            (unsigned int)record.sequence.i[0]*256 +(unsigned int)record.sequence.i[1],
            (unsigned int) _gnutls_uint64touint32 (packet_sequence), _gnutls_packet2str (record.type));
          goto sanity_check_error;
        }
      _gnutls_record_log
        ("REC[%p]: Decrypted Packet[%u.%u] %s(%d) with length: %d\n", session,
        (unsigned int)record.sequence.i[0]*256 +(unsigned int)record.sequence.i[1],
        (unsigned int) _gnutls_uint64touint32 (packet_sequence),
        _gnutls_packet2str (record.type), record.type, (int)_mbuffer_get_udata_size(decrypted));
    }
  else
    {
      _gnutls_record_log
        ("REC[%p]: Decrypted Packet[%u] %s(%d) with length: %d\n", session,
        (unsigned int) _gnutls_uint64touint32 (packet_sequence),
        _gnutls_packet2str (record.type), record.type, (int)_mbuffer_get_udata_size(decrypted));
    }

  /* increase sequence number 
   */
  if (!IS_DTLS(session) && sequence_increment (session, &record_state->sequence_number) != 0)
    {
      session_invalidate (session);
      gnutls_assert ();
      ret = GNUTLS_E_RECORD_LIMIT_REACHED;
      goto sanity_check_error;
    }

/* (originally for) TLS 1.0 CBC protection. 
 * Actually this code is called if we just received
 * an empty packet. An empty TLS packet is usually
 * sent to protect some vulnerabilities in the CBC mode.
 * In that case we go to the beginning and start reading
 * the next packet.
 */
  if (_mbuffer_get_udata_size(decrypted) == 0)
    {
      _mbuffer_xfree(&decrypted);
      empty_fragments++;
      goto begin;
    }

  if (record.v2)
    decrypted->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;
  else
    {
      uint8_t * p = _mbuffer_get_udata_ptr(decrypted);
      decrypted->htype = p[0];
    }

  ret =
    record_add_to_buffers (session, &record, type, htype, 
                           packet_sequence, decrypted);

  /* bufel is now either deinitialized or buffered somewhere else */

  if (ret < 0)
    return gnutls_assert_val(ret);

  return ret;

discard:
  session->internals.dtls.packets_dropped++;

  /* discard the whole received fragment. */
  bufel = _mbuffer_head_pop_first(&session->internals.record_recv_buffer);
  _mbuffer_xfree(&bufel);
  return gnutls_assert_val(GNUTLS_E_AGAIN);

sanity_check_error:
  if (IS_DTLS(session))
    {
      session->internals.dtls.packets_dropped++;
      ret = gnutls_assert_val(GNUTLS_E_AGAIN);
      goto cleanup;
    }

  session_unresumable (session);
  session_invalidate (session);

cleanup:
  _mbuffer_xfree(&decrypted);
  return ret;

recv_error:
  if (ret < 0 && (gnutls_error_is_fatal (ret) == 0 || ret == GNUTLS_E_TIMEDOUT))
    return ret;

  if (type == GNUTLS_ALERT) /* we were expecting close notify */
    {
      session_invalidate (session);
      gnutls_assert ();
      return 0;             
    }

  if (IS_DTLS(session))
    {
      goto discard;
    }

  session_invalidate (session);
  session_unresumable (session);

  if (ret == 0)
    return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
  else
    return ret;
}