]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
_gnutls_send_tlen_int() accepts the actual pad rather than the intended data. Correct...
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 1 Sep 2013 13:37:10 +0000 (16:37 +0300)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 1 Sep 2013 13:37:10 +0000 (16:37 +0300)
lib/gnutls_cipher.c
lib/gnutls_cipher.h
lib/gnutls_cipher_int.c
lib/gnutls_int.h
lib/gnutls_range.c
lib/gnutls_record.c
lib/gnutls_record.h

index db09a1b42776e7bf4341eea42f971a02aaf56987..da710fe9dcce18c5afb36f63fa1a8628bd1eb6a0 100644 (file)
@@ -45,7 +45,7 @@
 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,
@@ -64,7 +64,7 @@ static int
 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);
 
@@ -94,7 +94,7 @@ is_read_comp_null (record_parameters_st * record_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)
@@ -134,11 +134,11 @@ _gnutls_encrypt (gnutls_session_t session,
   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);
@@ -306,7 +306,7 @@ 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)
 {
@@ -349,7 +349,7 @@ compressed_to_ciphertext (gnutls_session_t session,
       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,
@@ -442,11 +442,11 @@ static int
 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;
@@ -459,7 +459,7 @@ compressed_to_ciphertext_new (gnutls_session_t session,
   int explicit_iv = _gnutls_version_has_explicit_iv (ver);
   int auth_cipher = _gnutls_auth_cipher_is_aead(&params->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);
@@ -544,15 +544,36 @@ compressed_to_ciphertext_new (gnutls_session_t session,
   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;
@@ -560,6 +581,8 @@ compressed_to_ciphertext_new (gnutls_session_t session,
 
   if (tag_size > 0)
     {
+      DECR_LEN(cipher_size, tag_size);
+
       data_ptr += tag_size;
       
       /* In AEAD ciphers we don't encrypt the tag 
@@ -583,7 +606,7 @@ compressed_to_ciphertext_new (gnutls_session_t session,
   ret =
     _gnutls_auth_cipher_encrypt2_tag (&params->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);
 
@@ -907,6 +930,9 @@ ciphertext_to_compressed_new (gnutls_session_t restrict session,
         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:
index 0e8dd7e10934f2bd034315ea1f48028f48d7be4a..cc4a1a08f16ac8cacd0d035ec8aad95b3c30f3be 100644 (file)
@@ -22,7 +22,7 @@
 
 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);
index fb54be082160c7f99b19f90d135b21c2138b3deb..129c6b42faaf23ce12d59e83e814cb8319e9f2af 100644 (file)
@@ -328,6 +328,8 @@ int ret;
     {
       _gnutls_cipher_tag(&handle->cipher, tag, tag_size);
     }
+  else
+    memset(tag, 0, tag_size);
     
   return 0;
 }
index bffa3e41d79965662f409bba2362de6f59f0d449..2c892f5166a4c0dfae145acb3ab22dadf36a283c 100644 (file)
@@ -182,7 +182,6 @@ typedef enum record_flush_t
 #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
@@ -1062,4 +1061,23 @@ unsigned int
 /* 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 */
index 67c39287d8611afb7a1f98a73849e6ba36046375..a087ff9a324f8e032df1154557147d03d5c77fac 100644 (file)
@@ -59,7 +59,7 @@ _gnutls_range_max_lh_pad (gnutls_session_t session, ssize_t data_length,
 
   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
@@ -163,9 +163,16 @@ gnutls_range_split (gnutls_session_t session,
                     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)
     {
@@ -283,7 +290,7 @@ gnutls_record_send_range (gnutls_session_t session, const void *data,
                                    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)
index d261585e22ebf027599b624c92aec36f2f5f0e89..bc6208149554b7de5433119af6106af67901e591 100644 (file)
@@ -427,7 +427,7 @@ sequence_increment (gnutls_session_t session,
  * @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.
@@ -443,7 +443,7 @@ 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)
+               size_t data_size, size_t min_pad, unsigned int mflags)
 {
   mbuffer_st *bufel;
   ssize_t cipher_size;
@@ -453,6 +453,7 @@ _gnutls_send_tlen_int (gnutls_session_t session, content_type_t type,
   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);
@@ -483,13 +484,14 @@ _gnutls_send_tlen_int (gnutls_session_t session, content_type_t type,
         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;
@@ -509,7 +511,7 @@ _gnutls_send_tlen_int (gnutls_session_t session, content_type_t type,
     }
   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
@@ -530,15 +532,15 @@ _gnutls_send_tlen_int (gnutls_session_t session, content_type_t type,
         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)
         {
index 0e215521517800fe235b7731912e1eaeca38773a..5c85dedf5340c5a55aa21ea1dc861784b3062b3f 100644 (file)
@@ -30,7 +30,7 @@ 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 sizeofdata, 
-                               size_t targetlength,
+                               size_t min_pad,
                                unsigned int mflags);
 
 inline static ssize_t
@@ -39,7 +39,7 @@ _gnutls_send_int (gnutls_session_t session, content_type_t type,
                   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,