summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2018-11-19 11:44:58 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2018-11-19 11:44:58 +0000
commit639d1df7e4e249559b4a20b9eaad57a93b2ecdce (patch)
tree7eb7d64006e7c0a540fedffb5afdce0c65d6f7b0
parent5ad1afa2c65c1ce9d0946dbb835edf93ec6d0ead (diff)
parent01202d84f45c62cf1e0499fbe012ffa5f02b9e17 (diff)
downloadgnutls-639d1df7e4e249559b4a20b9eaad57a93b2ecdce.tar.gz
Merge branch 'tmp-fix-max-early-data-size' into 'master'
Fix max_early_data_size handling See merge request gnutls/gnutls!811
-rw-r--r--lib/record.c11
-rw-r--r--lib/state.c3
-rw-r--r--lib/tls13/session_ticket.c6
-rw-r--r--src/serv-args.def8
-rw-r--r--src/serv.c10
-rwxr-xr-xtests/suite/testcompat-tls13-openssl.sh18
-rw-r--r--tests/tls13-early-data.c34
7 files changed, 77 insertions, 13 deletions
diff --git a/lib/record.c b/lib/record.c
index 5514ddcef1..19f5b52282 100644
--- a/lib/record.c
+++ b/lib/record.c
@@ -52,6 +52,7 @@
#include <dtls.h>
#include <dh.h>
#include <random.h>
+#include <xsize.h>
struct tls_record_st {
uint16_t header_size;
@@ -2041,7 +2042,9 @@ gnutls_record_send2(gnutls_session_t session, const void *data,
* as gnutls_record_send().
*
* There may be a limit to the amount of data sent as early data. Use
- * gnutls_record_get_max_early_data_size() to check the limit.
+ * gnutls_record_get_max_early_data_size() to check the limit. If the
+ * limit exceeds, this function returns
+ * %GNUTLS_E_RECORD_LIMIT_REACHED.
*
* Returns: The number of bytes sent, or a negative error code. The
* number of bytes sent might be less than @data_size. The maximum
@@ -2059,6 +2062,12 @@ ssize_t gnutls_record_send_early_data(gnutls_session_t session,
if (session->security_parameters.entity != GNUTLS_CLIENT)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (xsum(session->internals.
+ early_data_presend_buffer.length,
+ data_size) >
+ session->security_parameters.max_early_data_size)
+ return gnutls_assert_val(GNUTLS_E_RECORD_LIMIT_REACHED);
+
ret =
_gnutls_buffer_append_data(&session->internals.
early_data_presend_buffer, data,
diff --git a/lib/state.c b/lib/state.c
index 5364d5e727..7e6354f9fe 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -518,6 +518,9 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags)
if ((*session)->security_parameters.entity == GNUTLS_SERVER) {
(*session)->security_parameters.max_early_data_size =
DEFAULT_MAX_EARLY_DATA_SIZE;
+ } else {
+ (*session)->security_parameters.max_early_data_size =
+ UINT32_MAX;
}
/* everything else not initialized here is initialized
diff --git a/lib/tls13/session_ticket.c b/lib/tls13/session_ticket.c
index 7ea2b00f82..f254a73036 100644
--- a/lib/tls13/session_ticket.c
+++ b/lib/tls13/session_ticket.c
@@ -388,12 +388,10 @@ static int parse_nst_extension(void *ctx, unsigned tls_id, const unsigned char *
{
gnutls_session_t session = ctx;
if (tls_id == ext_mod_early_data.tls_id) {
- uint32_t size;
if (data_size < 4)
return gnutls_assert_val(GNUTLS_E_TLS_PACKET_DECODING_ERROR);
- size = _gnutls_read_uint32(data);
- if (size < session->security_parameters.max_early_data_size)
- session->security_parameters.max_early_data_size = size;
+ session->security_parameters.max_early_data_size =
+ _gnutls_read_uint32(data);
}
return 0;
}
diff --git a/src/serv-args.def b/src/serv-args.def
index 6c17998da0..7c4c32479c 100644
--- a/src/serv-args.def
+++ b/src/serv-args.def
@@ -49,6 +49,14 @@ flag = {
};
flag = {
+ name = maxearlydata;
+ arg-type = number;
+ arg-range = "1->4294967296";
+ descrip = "The maximum early data size to accept";
+ doc = "";
+};
+
+flag = {
name = nocookie;
descrip = "Don't require cookie on DTLS sessions";
doc = "";
diff --git a/src/serv.c b/src/serv.c
index d0b5914bc0..2ceb3dbf1f 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -408,8 +408,16 @@ gnutls_session_t initialize_session(int dtls)
gnutls_session_ticket_enable_server(session,
&session_ticket_key);
- if (earlydata)
+ if (earlydata) {
gnutls_anti_replay_enable(session, anti_replay);
+ if (HAVE_OPT(MAXEARLYDATA)) {
+ ret = gnutls_record_set_max_early_data_size(session, OPT_VALUE_MAXEARLYDATA);
+ if (ret < 0) {
+ fprintf(stderr, "Could not set max early data size: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+ }
+ }
if (sni_hostname != NULL)
gnutls_handshake_set_post_client_hello_function(session,
diff --git a/tests/suite/testcompat-tls13-openssl.sh b/tests/suite/testcompat-tls13-openssl.sh
index c573182870..27ca3826e3 100755
--- a/tests/suite/testcompat-tls13-openssl.sh
+++ b/tests/suite/testcompat-tls13-openssl.sh
@@ -530,6 +530,24 @@ _EOF_
kill ${PID}
wait
+
+ echo_cmd "${PREFIX}Checking TLS 1.3 with resumption and early data with small limit..."
+ testdir=`create_testdir tls13-openssl-resumption`
+ eval "${GETPORT}"
+ launch_server $$ --priority "NORMAL:-VERS-ALL:+VERS-TLS1.3${ADD}" --x509certfile "${RSA_CERT}" --x509keyfile "${RSA_KEY}" --x509cafile "${CA_CERT}" --earlydata --maxearlydata 1 >>${OUTPUT} 2>&1
+ PID=$!
+ wait_server ${PID}
+
+ echo "This file contains early data sent by the client" > "${testdir}/earlydata.txt"
+ { echo a; sleep 1; } | \
+ ${OPENSSL_CLI} s_client -host localhost -port "${PORT}" -CAfile "${CA_CERT}" -sess_out "${testdir}/sess-earlydata.pem" 2>&1 | grep "\:error\:" && \
+ fail ${PID} "Failed"
+ ${OPENSSL_CLI} s_client -host localhost -port "${PORT}" -CAfile "${CA_CERT}" -sess_in "${testdir}/sess-earlydata.pem" -early_data "${testdir}/earlydata.txt" </dev/null 2>&1 > "${testdir}/server.out"
+ grep "^Early data was rejected" "${testdir}/server.out" || \
+ fail ${PID} "Failed"
+
+ kill ${PID}
+ wait
rm -rf "${testdir}"
}
diff --git a/tests/tls13-early-data.c b/tests/tls13-early-data.c
index c922ae0ba6..e98f394dac 100644
--- a/tests/tls13-early-data.c
+++ b/tests/tls13-early-data.c
@@ -51,6 +51,7 @@ int main(void)
#include "cert-common.h"
#include "utils.h"
#include "virt-time.h"
+#define MIN(x,y) (((x)<(y))?(x):(y))
/* This program tests the robustness of record sending with padding.
*/
@@ -94,7 +95,7 @@ gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len)
return 0;
}
-static void client(int sds[])
+static void client(int sds[], const char *data, size_t size, size_t maxsize)
{
int ret;
char buffer[MAX_BUF + 1];
@@ -127,7 +128,12 @@ static void client(int sds[])
if (t > 0) {
assert(gnutls_session_set_data(session, session_data.data, session_data.size) >= 0);
- assert(gnutls_record_send_early_data(session, EARLY_MSG, sizeof(EARLY_MSG)) >= 0);
+ /* The server should have advertised the same maximum. */
+ if (gnutls_record_get_max_early_data_size(session) != maxsize)
+ fail("client: max_early_data_size mismatch %d != %d\n",
+ (int) gnutls_record_get_max_early_data_size(session),
+ (int) maxsize);
+ assert(gnutls_record_send_early_data(session, data, MIN(size, maxsize)) >= 0);
assert(gnutls_handshake_set_random(session, &hrnd) >= 0);
}
@@ -242,7 +248,7 @@ storage_clear(struct storage_st *storage)
storage->num_entries = 0;
}
-static void server(int sds[])
+static void server(int sds[], const char *data, size_t size, size_t maxsize)
{
int ret;
char buffer[MAX_BUF + 1];
@@ -292,6 +298,12 @@ static void server(int sds[])
gnutls_anti_replay_enable(session, anti_replay);
+ /* on the replay connection, early data is skipped
+ * until max_early_data_size without decryption
+ */
+ if (t < 2)
+ (void) gnutls_record_set_max_early_data_size(session, maxsize);
+
gnutls_transport_set_int(session, sd);
do {
@@ -330,7 +342,8 @@ static void server(int sds[])
gnutls_strerror(ret));
}
- if (ret != sizeof(EARLY_MSG) || memcmp(buffer, EARLY_MSG, ret))
+ if ((size_t) ret != MIN(size, maxsize) ||
+ memcmp(buffer, data, ret))
fail("server: early data mismatch\n");
} else {
if (gnutls_rnd_works) {
@@ -387,7 +400,8 @@ static void server(int sds[])
success("server: finished\n");
}
-void doit(void)
+static void
+start(const char *data, size_t size, size_t maxsize)
{
int client_sds[SESSIONS], server_sds[SESSIONS];
int i;
@@ -420,14 +434,20 @@ void doit(void)
/* parent */
for (i = 0; i < SESSIONS; i++)
close(client_sds[i]);
- server(server_sds);
+ server(server_sds, data, size, maxsize);
kill(child, SIGTERM);
} else {
for (i = 0; i < SESSIONS; i++)
close(server_sds[i]);
- client(client_sds);
+ client(client_sds, data, size, maxsize);
exit(0);
}
}
+void doit(void)
+{
+ start(EARLY_MSG, sizeof(EARLY_MSG), MAX_BUF);
+ start(EARLY_MSG, sizeof(EARLY_MSG), 10);
+}
+
#endif /* _WIN32 */