static int compressed_to_ciphertext (gnutls_session_t session,
uint8_t * cipher_data, int cipher_size,
gnutls_datum_t *compressed,
- size_t target_size,
+ size_t min_pad,
content_type_t _type,
record_parameters_st * params);
static int ciphertext_to_compressed (gnutls_session_t session,
compressed_to_ciphertext_new (gnutls_session_t session,
uint8_t * cipher_data, int cipher_size,
gnutls_datum_t *compressed,
- size_t target_size,
+ size_t min_pad,
content_type_t type,
record_parameters_st * params);
int
_gnutls_encrypt (gnutls_session_t session,
const uint8_t * data, size_t data_size,
- size_t target_size,
+ size_t min_pad,
mbuffer_st* bufel,
content_type_t type,
record_parameters_st * params)
if (params->write.new_record_padding != 0)
ret = compressed_to_ciphertext_new (session, _mbuffer_get_udata_ptr(bufel),
_mbuffer_get_udata_size(bufel),
- &comp, target_size, type, params);
+ &comp, min_pad, type, params);
else
ret = compressed_to_ciphertext (session, _mbuffer_get_udata_ptr(bufel),
_mbuffer_get_udata_size(bufel),
- &comp, target_size, type, params);
+ &comp, min_pad, type, params);
if (free_comp)
gnutls_free(comp.data);
compressed_to_ciphertext (gnutls_session_t session,
uint8_t * cipher_data, int cipher_size,
gnutls_datum_t *compressed,
- size_t target_size,
+ size_t min_pad,
content_type_t type,
record_parameters_st * params)
{
if (ret < 0)
return gnutls_assert_val(ret);
- pad = target_size - compressed->size;
+ pad = min_pad;
length =
calc_enc_length_block (session, ver, compressed->size, tag_size, &pad,
compressed_to_ciphertext_new (gnutls_session_t session,
uint8_t * cipher_data, int cipher_size,
gnutls_datum_t *compressed,
- size_t target_size,
+ size_t min_pad,
content_type_t type,
record_parameters_st * params)
{
- uint16_t pad = target_size - compressed->size;
+ uint16_t pad = min_pad;
int length, length_to_encrypt, ret;
uint8_t preamble[MAX_PREAMBLE_SIZE];
int preamble_size;
int explicit_iv = _gnutls_version_has_explicit_iv (ver);
int auth_cipher = _gnutls_auth_cipher_is_aead(¶ms->write.cipher_state);
uint8_t nonce[MAX_CIPHER_BLOCK_SIZE];
- unsigned iv_size;
+ unsigned iv_size, final_cipher_size;
if (unlikely(ver == NULL))
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
data_ptr += 2;
length_to_encrypt += 2;
length += 2;
-
+ final_cipher_size = cipher_size;
+
if (pad > 0)
{
+ unsigned t;
+
+ t = cipher_size - compressed->size;
+ if (pad > t)
+ {
+ if (block_algo == CIPHER_BLOCK)
+ {
+ if (pad <= blocksize)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ pad -= blocksize*((pad-t)/blocksize);
+ }
+ else
+ pad = t;
+ }
+
+ DECR_LEN(cipher_size, pad);
+
memset(data_ptr, 0, pad);
data_ptr += pad;
length_to_encrypt += pad;
length += pad;
}
+ DECR_LEN(cipher_size, compressed->size);
+
memcpy (data_ptr, compressed->data, compressed->size);
data_ptr += compressed->size;
length_to_encrypt += compressed->size;
if (tag_size > 0)
{
+ DECR_LEN(cipher_size, tag_size);
+
data_ptr += tag_size;
/* In AEAD ciphers we don't encrypt the tag
ret =
_gnutls_auth_cipher_encrypt2_tag (¶ms->write.cipher_state,
cipher_data, length_to_encrypt,
- cipher_data, cipher_size, 0);
+ cipher_data, final_cipher_size, 0);
if (ret < 0)
return gnutls_assert_val(ret);
return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
length_to_decrypt = ciphertext->size;
+ if (length_to_decrypt < blocksize)
+ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
break;
default:
int _gnutls_encrypt (gnutls_session_t session,
const uint8_t * data,
- size_t data_size, size_t target_size,
+ size_t data_size, size_t min_pad,
mbuffer_st* bufel,
content_type_t type,
record_parameters_st * params);
{
_gnutls_cipher_tag(&handle->cipher, tag, tag_size);
}
+ else
+ memset(tag, 0, tag_size);
return 0;
}
#define RECORD_HEADER_SIZE(session) (IS_DTLS(session) ? DTLS_RECORD_HEADER_SIZE : TLS_RECORD_HEADER_SIZE)
#define MAX_RECORD_HEADER_SIZE DTLS_RECORD_HEADER_SIZE
-#define MAX_USER_SEND_SIZE(session) (IS_DTLS(session)?((size_t)gnutls_dtls_get_data_mtu(session)):(size_t)session->security_parameters.max_record_send_size)
#define MAX_RECORD_SEND_SIZE(session) (IS_DTLS(session)?((size_t)gnutls_dtls_get_mtu(session)):(size_t)session->security_parameters.max_record_send_size+MAX_RECORD_OVERHEAD(session))
#define MAX_RECORD_RECV_SIZE(session) ((size_t)session->security_parameters.max_record_recv_size)
#define MAX_PAD_SIZE 255
/* returns a-b in ms */
timespec_sub_ms (struct timespec *a, struct timespec *b);
+#include <algorithms.h>
+inline static size_t max_user_send_size(gnutls_session_t session, record_parameters_st *record_params)
+{
+size_t max;
+
+ if (IS_DTLS(session))
+ max = gnutls_dtls_get_data_mtu(session);
+ else
+ max = session->security_parameters.max_record_send_size;
+
+ if (record_params->write.new_record_padding != 0)
+ max -= 2;
+
+ if (_gnutls_cipher_is_block (record_params->cipher))
+ max -= _gnutls_cipher_get_block_size(record_params->cipher);
+
+ return max;
+}
+
#endif /* GNUTLS_INT_H */
if (session->security_parameters.new_record_padding != 0)
{
- max_pad = MAX_USER_SEND_SIZE (session);
+ max_pad = max_user_send_size (session, record_params);
fixed_pad = 2;
}
else
gnutls_range_st * remainder)
{
int ret;
- ssize_t max_frag = MAX_USER_SEND_SIZE (session);
+ ssize_t max_frag;
ssize_t orig_low = (ssize_t) orig->low;
ssize_t orig_high = (ssize_t) orig->high;
+ record_parameters_st *record_params;
+
+ ret = _gnutls_epoch_get (session, EPOCH_WRITE_CURRENT, &record_params);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ max_frag = max_user_send_size (session, record_params);
if (orig_high == orig_low)
{
EPOCH_WRITE_CURRENT,
&(((char *) data)[sent]),
next_fragment_length,
- cur_range.high,
+ cur_range.high-next_fragment_length,
MBUFFER_FLUSH);
while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
* @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
+ * @min_pad: the minimum required padding
* @mflags: zero or %MBUFFER_FLUSH
*
* Oct 30 2001: Removed capability to send data more than MAX_RECORD_SIZE.
_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)
+ size_t data_size, size_t min_pad, unsigned int mflags)
{
mbuffer_st *bufel;
ssize_t cipher_size;
int header_size;
const uint8_t *data = _data;
record_parameters_st *record_params;
+ size_t max_send_size;
record_state_st *record_state;
ret = _gnutls_epoch_get (session, epoch_rel, &record_params);
return GNUTLS_E_INVALID_SESSION;
}
+ max_send_size = max_user_send_size(session, record_params);
- if (data_size > MAX_USER_SEND_SIZE(session))
+ if (data_size > max_send_size)
{
if (IS_DTLS(session))
return gnutls_assert_val(GNUTLS_E_LARGE_PACKET);
- send_data_size = MAX_USER_SEND_SIZE(session);
+ send_data_size = max_send_size;
}
else
send_data_size = data_size;
}
else
{
- if (unlikely((send_data_size == 0 && target_length == 0)))
+ if (unlikely((send_data_size == 0 && min_pad == 0)))
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
/* now proceed to packet encryption
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);
+ ("REC[%p]: Preparing Packet %s(%d) with length: %d and min pad: %d\n", session,
+ _gnutls_packet2str (type), type, (int) data_size, (int) min_pad);
_mbuffer_set_udata_size(bufel, cipher_size);
_mbuffer_set_uhead_size(bufel, header_size);
ret =
_gnutls_encrypt (session,
- data, send_data_size, target_length,
+ data, send_data_size, min_pad,
bufel, type, record_params);
if (ret <= 0)
{
gnutls_handshake_description_t htype,
unsigned int epoch_rel, const void *data,
size_t sizeofdata,
- size_t targetlength,
+ size_t min_pad,
unsigned int mflags);
inline static ssize_t
unsigned int epoch_rel, const void *_data,
size_t data_size, unsigned int mflags)
{
- return _gnutls_send_tlen_int(session,type,htype,epoch_rel,_data,data_size,data_size,mflags);
+ return _gnutls_send_tlen_int(session,type,htype,epoch_rel,_data,data_size,0,mflags);
}
ssize_t _gnutls_recv_int (gnutls_session_t session, content_type_t type,