コード例 #1
0
ファイル: gnutls_dtls.c プロジェクト: philippe-goetz/gnutls
/**
 * gnutls_dtls_get_data_mtu:
 * @session: is a #gnutls_session_t structure.
 *
 * This function will return the actual maximum transfer unit for
 * application data. I.e. DTLS headers are subtracted from the
 * actual MTU.
 *
 * Returns: the maximum allowed transfer unit.
 *
 * Since: 3.0
 **/
unsigned int gnutls_dtls_get_data_mtu (gnutls_session_t session)
{
int ret;

  ret = _gnutls_record_overhead_rt(session);
  if (ret >= 0)
    return session->internals.dtls.mtu - ret;
  else
    return session->internals.dtls.mtu - RECORD_HEADER_SIZE(session);
}
コード例 #2
0
ファイル: gnutls_dtls.c プロジェクト: nobled/gnutls
/**
 * gnutls_dtls_get_data_mtu:
 * @session: is a #gnutls_session_t structure.
 *
 * This function will return the actual maximum transfer unit for
 * application data. I.e. DTLS headers are subtracted from the
 * actual MTU.
 *
 * Returns: the maximum allowed transfer unit.
 *
 * Since: 3.0
 **/
unsigned int gnutls_dtls_get_data_mtu (gnutls_session_t session)
{
int mtu = session->internals.dtls.mtu;
unsigned int blocksize = 1;
int overhead;
 
  mtu -= RECORD_HEADER_SIZE(session);

  overhead = record_overhead_rt(session, &blocksize);
  if (overhead < 0)
    return mtu;

  if (blocksize)
    mtu -= mtu % blocksize;

  return mtu - overhead;
}
コード例 #3
0
ファイル: gnutls_dtls.c プロジェクト: nobled/gnutls
/**
 * gnutls_dtls_set_data_mtu:
 * @session: is a #gnutls_session_t structure.
 * @mtu: The maximum unencrypted transfer unit of the session
 *
 * This function will set the maximum size of the *unencrypted* records
 * which will be sent over a DTLS session. It is equivalent to calculating
 * the DTLS packet overhead with the current encryption parameters, and
 * calling gnutls_dtls_set_mtu() with that value. In particular, this means
 * that you may need to call this function again after any negotiation or
 * renegotiation, in order to ensure that the MTU is still sufficient to
 * account for the new protocol overhead.
 *
 * Returns: %GNUTLS_E_SUCCESS (0) on success, or a negative error code.
 *
 * Since: 3.1
 **/
int gnutls_dtls_set_data_mtu (gnutls_session_t session, unsigned int mtu)
{
  unsigned int blocksize;
  int overhead = record_overhead_rt(session, &blocksize);

  /* You can't call this until the session is actually running */
  if (overhead < 0)
	  return GNUTLS_E_INVALID_SESSION;

  /* Add the overhead inside the encrypted part */
  mtu += overhead;

  /* Round it up to the next multiple of blocksize */
  mtu += blocksize - 1;
  mtu -= mtu % blocksize;

  /* Add the *unencrypted header size */
  mtu += RECORD_HEADER_SIZE(session);

  gnutls_dtls_set_mtu(session, mtu);
  return GNUTLS_E_SUCCESS;
}
コード例 #4
0
ファイル: gnutls_record.c プロジェクト: frankmorgner/gnutls
/* This function behaves exactly like write(). The only difference is
 * that it accepts, the gnutls_session_t and the content_type_t of data to
 * send (if called by the user the Content is specific)
 * It is intended to transfer data, under the current session.    
 *
 * @type: The content type to send
 * @htype: If this is a handshake message then the handshake type
 * @epoch_rel: %EPOCH_READ_* or %EPOCH_WRITE_*
 * @data: the data to be sent
 * @data_size: the size of the @data
 * @target_length: @data_size + minimum required padding
 * @mflags: zero or %MBUFFER_FLUSH
 *
 * Oct 30 2001: Removed capability to send data more than MAX_RECORD_SIZE.
 * This makes the function much easier to read, and more error resistant
 * (there were cases were the old function could mess everything up).
 * --nmav
 *
 * This function may accept a NULL pointer for data, and 0 for size, if
 * and only if the previous send was interrupted for some reason.
 *
 */
ssize_t
_gnutls_send_tlen_int (gnutls_session_t session, content_type_t type,
		gnutls_handshake_description_t htype,
		unsigned int epoch_rel, const void *_data,
		size_t data_size, size_t target_length, unsigned int mflags)
{
  mbuffer_st *bufel;
  ssize_t cipher_size;
  int retval, ret;
  int send_data_size;
  uint8_t *headers;
  int header_size;
  const uint8_t *data = _data;
  record_parameters_st *record_params;
  record_state_st *record_state;

  ret = _gnutls_epoch_get (session, epoch_rel, &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_INVALID_REQUEST);

  record_state = &record_params->write;

  /* Do not allow null pointer if the send buffer is empty.
   * If the previous send was interrupted then a null pointer is
   * ok, and means to resume.
   */
  if (session->internals.record_send_buffer.byte_length == 0 &&
      (data_size == 0 && _data == NULL))
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (type != GNUTLS_ALERT)     /* alert messages are sent anyway */
    if (session_is_valid (session) || session->internals.may_not_write != 0)
      {
        gnutls_assert ();
        return GNUTLS_E_INVALID_SESSION;
      }


  if (data_size > MAX_USER_SEND_SIZE(session))
    {
      if (IS_DTLS(session))
        return gnutls_assert_val(GNUTLS_E_LARGE_PACKET);

      send_data_size = MAX_USER_SEND_SIZE(session);
    }
  else
    send_data_size = data_size;
  
  /* Only encrypt if we don't have data to send 
   * from the previous run. - probably interrupted.
   */
  if (mflags != 0 && session->internals.record_send_buffer.byte_length > 0)
    {
      ret = _gnutls_io_write_flush (session);
      if (ret > 0)
        cipher_size = ret;
      else
        cipher_size = 0;

      retval = session->internals.record_send_buffer_user_size;
    }
  else
    {
      if (unlikely((send_data_size == 0 && target_length == 0)))
        return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

      /* now proceed to packet encryption
       */
      cipher_size = MAX_RECORD_SEND_SIZE(session);
      bufel = _mbuffer_alloc (0, cipher_size+CIPHER_SLACK_SIZE);
      if (bufel == NULL)
        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

      headers = _mbuffer_get_uhead_ptr(bufel);
      headers[0] = type;
      /* Use the default record version, if it is
       * set. */
      copy_record_version (session, htype, &headers[1]);
      header_size = RECORD_HEADER_SIZE(session);
      /* Adjust header length and add sequence for DTLS */
      if (IS_DTLS(session))
        memcpy(&headers[3], &record_state->sequence_number.i, 8);

      _gnutls_record_log
        ("REC[%p]: Preparing Packet %s(%d) with length: %d and target length: %d\n", session,
         _gnutls_packet2str (type), type, (int) data_size, (int) target_length);

      _mbuffer_set_udata_size(bufel, cipher_size);
      _mbuffer_set_uhead_size(bufel, header_size);

      ret =
        _gnutls_encrypt (session, 
                         data, send_data_size, target_length, 
                         bufel, type, record_params);
      if (ret <= 0)
        {
          gnutls_assert ();
          if (ret == 0)
            ret = GNUTLS_E_ENCRYPTION_FAILED;
          gnutls_free (bufel);
          return ret;   /* error */
        }

      cipher_size = _mbuffer_get_udata_size(bufel);
      retval = send_data_size;
      session->internals.record_send_buffer_user_size = send_data_size;

      /* increase sequence number
       */
      if (sequence_increment (session, &record_state->sequence_number) != 0)
        {
          session_invalidate (session);
          gnutls_free (bufel);
          return gnutls_assert_val(GNUTLS_E_RECORD_LIMIT_REACHED);
        }

      ret = _gnutls_io_write_buffered (session, bufel, mflags);
    }

  if (ret != cipher_size)
    {
      /* If we have sent any data then just return
       * the error value. Do not invalidate the session.
       */
      if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
        return gnutls_assert_val(ret);

      if (ret > 0)
        ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

      session_unresumable (session);
      session->internals.may_not_write = 1;
      return gnutls_assert_val(ret);
    }

  session->internals.record_send_buffer_user_size = 0;

  _gnutls_record_log ("REC[%p]: Sent Packet[%d] %s(%d) in epoch %d and length: %d\n",
                      session,
                      (unsigned int)
                      _gnutls_uint64touint32
                      (&record_state->sequence_number),
                      _gnutls_packet2str (type), type, 
                      (int) record_params->epoch,
                      (int) cipher_size);

  return retval;
}
コード例 #5
0
ファイル: gnutls_record.c プロジェクト: frankmorgner/gnutls
static int recv_headers( gnutls_session_t session, content_type_t type, 
                         gnutls_handshake_description_t htype, 
                         struct tls_record_st* record,
                         unsigned int *ms)
{
int ret;
gnutls_datum_t raw; /* raw headers */
  /* Read the headers.
   */
  record->header_size = record->packet_size = RECORD_HEADER_SIZE(session);

  ret =
       _gnutls_io_read_buffered (session, record->header_size, -1, ms);
  if (ret != record->header_size)
    {
      if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
        return ret;
      
      if (ret > 0)
        ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
      else if (ret == 0)
        ret = GNUTLS_E_PREMATURE_TERMINATION;

      return gnutls_assert_val(ret);
    }

  ret = _mbuffer_linearize (&session->internals.record_recv_buffer);
  if (ret < 0)
    return gnutls_assert_val(ret);

  _mbuffer_head_get_first (&session->internals.record_recv_buffer, &raw);
  if (raw.size < RECORD_HEADER_SIZE(session))
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

  record_read_headers (session, raw.data, type, htype, record);

  /* Check if the DTLS epoch is valid */
  if (IS_DTLS(session)) 
    {
      if (_gnutls_epoch_is_valid(session, record->epoch) == 0)
        {
          _gnutls_audit_log(session, "Discarded message[%u] with invalid epoch %u.\n",
            (unsigned int)_gnutls_uint64touint32 (&record->sequence), 
            (unsigned int)record->sequence.i[0]*256+(unsigned int)record->sequence.i[1]);
          gnutls_assert();
          /* doesn't matter, just a fatal error */
          return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
        }
    }

  /* Here we check if the Type of the received packet is
   * ok. 
   */
  if ((ret = check_recv_type (session, record->type)) < 0)
    return gnutls_assert_val(ret);

  /* Here we check if the advertized version is the one we
   * negotiated in the handshake.
   */
  if ((ret = record_check_version (session, htype, record->version)) < 0)
    return gnutls_assert_val(ret);

  if (record->length > MAX_RECV_SIZE(session))
    {
      _gnutls_audit_log
        (session, "Received packet with illegal length: %u\n", (unsigned int)record->length);
      return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
    }

  _gnutls_record_log
    ("REC[%p]: Expected Packet %s(%d)\n", session,
     _gnutls_packet2str (type), type);
  _gnutls_record_log ("REC[%p]: Received Packet %s(%d) with length: %d\n",
                      session,
                      _gnutls_packet2str (record->type), record->type, record->length);

  
  return 0;
}