]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
gnutls_dtls_get_data_mtu() is more precise. Based on patch by David Woodhouse.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 29 Jun 2012 22:35:56 +0000 (00:35 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 29 Jun 2012 22:35:56 +0000 (00:35 +0200)
lib/gnutls_dtls.c
lib/gnutls_int.h
lib/gnutls_state.c
lib/gnutls_state.h

index f07b300cbcdb02744fad28d395b7eb4a0c79e69b..979198cc2e037849333c0d6ee4e47e2f65937c4c 100644 (file)
@@ -581,6 +581,63 @@ void gnutls_dtls_set_mtu (gnutls_session_t session, unsigned int mtu)
   session->internals.dtls.mtu  = mtu;
 }
 
+/* returns overhead imposed by the record layer (encryption/compression)
+ * etc. It does not include the record layer headers, since the caller
+ * needs to cope with rounding to multiples of blocksize, and the header
+ * is outside that.
+ *
+ * blocksize: will contain the block size when padding may be required or 1
+ *
+ * It may return a negative error code on error.
+ */
+static int _gnutls_record_overhead_rt(gnutls_session_t session, unsigned int *blocksize)
+{
+record_parameters_st *params;
+int total = 0, ret, iv_size;
+
+  if (session->internals.initial_negotiation_completed == 0)
+    return GNUTLS_E_INVALID_REQUEST;
+
+  ret = _gnutls_epoch_get (session, EPOCH_WRITE_CURRENT, &params);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  /* requires padding */
+  iv_size = _gnutls_cipher_get_iv_size(params->cipher_algorithm);
+
+  if (_gnutls_cipher_is_block (params->cipher_algorithm) == CIPHER_BLOCK)
+    {
+      *blocksize = iv_size;
+
+      if (!IS_DTLS(session))
+        total += MAX_PAD_SIZE;
+      else
+        total += iv_size; /* iv_size == block_size */
+    }
+  else
+    {
+      *blocksize = 1;
+    }
+  
+  if (params->mac_algorithm == GNUTLS_MAC_AEAD)
+    total += _gnutls_cipher_get_tag_size(params->cipher_algorithm);
+  else
+    {
+      ret = _gnutls_hmac_get_algo_len(params->mac_algorithm);
+      if (ret < 0)
+        return gnutls_assert_val(ret);
+      total+=ret;
+    }
+
+  if (params->compression_algorithm != GNUTLS_COMP_NULL)
+    total += EXTRA_COMP_SIZE;
+  
+  /* We always pad with at least one byte; never 0. */
+  total++;
+
+  return total;
+}
+
 /**
  * gnutls_dtls_get_data_mtu:
  * @session: is a #gnutls_session_t structure.
@@ -595,13 +652,20 @@ void gnutls_dtls_set_mtu (gnutls_session_t session, unsigned int mtu)
  **/
 unsigned int gnutls_dtls_get_data_mtu (gnutls_session_t session)
 {
-int ret;
+int mtu = session->internals.dtls.mtu;
+int blocksize = 0;
+int overhead;
+  mtu -= RECORD_HEADER_SIZE(session);
 
-  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);
+  overhead = _gnutls_record_overhead_rt(session, &blocksize);
+  if (overhead < 0)
+    return mtu;
+
+  if (blocksize)
+    mtu -= mtu % blocksize;
+
+  return mtu - overhead;
 }
 
 /**
index 02c4f9524cfd4f77704122d6548ea71920e3a8db..77705a304f361aa521c0c2db77899ae09924c0b4 100644 (file)
@@ -82,6 +82,7 @@ typedef struct
 } uint64;
 
 #include <gnutls/gnutls.h>
+#include <gnutls/dtls.h>
 #include <gnutls/abstract.h>
 #include <system.h>
 
@@ -174,7 +175,7 @@ typedef enum transport_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_RECORD_SEND_SIZE(session) (IS_DTLS(session)?((size_t)session->internals.dtls.mtu-DTLS_RECORD_HEADER_SIZE):(size_t)session->security_parameters.max_record_send_size)
+#define MAX_RECORD_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_RECV_SIZE(session) ((size_t)session->security_parameters.max_record_recv_size)
 #define MAX_PAD_SIZE 255
 #define EXTRA_COMP_SIZE 2048
index 6fae277de96ca9c150a116c95f4d5267b95d0c99..c868d48d9ef6efe25eda96d74b56e582fb33dfe4 100644 (file)
@@ -1353,53 +1353,6 @@ gnutls_session_channel_binding (gnutls_session_t session,
   return 0;
 }
 
-/* returns overhead imposed by the record layer (encryption/compression)
- * etc. It does include the record layer headers.
- *
- * It may return a negative error code on error.
- */
-int _gnutls_record_overhead_rt(gnutls_session_t session)
-{
-record_parameters_st *params;
-int total = 0, ret, iv_size;
-
-  if (session->internals.initial_negotiation_completed == 0)
-    return RECORD_HEADER_SIZE(session);
-
-  ret = _gnutls_epoch_get (session, EPOCH_WRITE_CURRENT, &params);
-  if (ret < 0)
-    return gnutls_assert_val(ret);
-
-  /* requires padding */
-  iv_size = _gnutls_cipher_get_iv_size(params->cipher_algorithm);
-  total += iv_size;
-
-  if (_gnutls_cipher_is_block (params->cipher_algorithm) == CIPHER_BLOCK)
-    {
-      if (!IS_DTLS(session))
-        total += MAX_PAD_SIZE;
-      else
-        total += iv_size; /* iv_size == block_size */
-    }
-  
-  if (params->mac_algorithm == GNUTLS_MAC_AEAD)
-    total += _gnutls_cipher_get_tag_size(params->cipher_algorithm);
-  else
-    {
-      ret = _gnutls_hmac_get_algo_len(params->mac_algorithm);
-      if (ret < 0)
-        return gnutls_assert_val(ret);
-      total+=ret;
-    }
-
-  if (params->compression_algorithm != GNUTLS_COMP_NULL)
-    total += EXTRA_COMP_SIZE;
-  
-  total += RECORD_HEADER_SIZE(session);
-  
-  return total;
-}
-
 /**
  * gnutls_ecc_curve_get:
  * @session: is a #gnutls_session_t structure.
index b2e5511f16e3c039f7ad1d7665692f28550530e3..a89e1817e699b9994b7f3a52625fe2a3267d94bc 100644 (file)
@@ -43,8 +43,6 @@ void
 _gnutls_record_set_default_version (gnutls_session_t session,
                                     unsigned char major, unsigned char minor);
 
-int _gnutls_record_overhead_rt(gnutls_session_t session);
-
 #include <gnutls_auth.h>
 
 #define CHECK_AUTH(auth, ret) if (gnutls_auth_get_type(session) != auth) { \