summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2012-06-30 00:35:56 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2012-06-30 00:35:56 +0200
commitceb092a86ca3c6eb1030f90d842962278e52970d (patch)
tree9368ba28cb55393da44545946cd87c6c08ca0052
parentebc0ed0dbbea6926c9345653cf7d5ff4dbcc424f (diff)
downloadgnutls-ceb092a86ca3c6eb1030f90d842962278e52970d.tar.gz
gnutls_dtls_get_data_mtu() is more precise. Based on patch by David Woodhouse.
-rw-r--r--lib/gnutls_dtls.c76
-rw-r--r--lib/gnutls_int.h3
-rw-r--r--lib/gnutls_state.c47
-rw-r--r--lib/gnutls_state.h2
4 files changed, 72 insertions, 56 deletions
diff --git a/lib/gnutls_dtls.c b/lib/gnutls_dtls.c
index f07b300cbc..979198cc2e 100644
--- a/lib/gnutls_dtls.c
+++ b/lib/gnutls_dtls.c
@@ -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;
}
/**
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 02c4f9524c..77705a304f 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -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
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index 6fae277de9..c868d48d9e 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -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.
diff --git a/lib/gnutls_state.h b/lib/gnutls_state.h
index b2e5511f16..a89e1817e6 100644
--- a/lib/gnutls_state.h
+++ b/lib/gnutls_state.h
@@ -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) { \