summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2018-10-12 13:34:21 +0200
committerDaiki Ueno <dueno@redhat.com>2018-11-11 07:03:44 +0100
commit6cf6b8f7205adbff41f38320433fb70ea4546720 (patch)
tree53020c29200ff4b65804b4f10122ecc7f4da68df
parent957f7537604b21653c0d456e55fabed600052508 (diff)
downloadgnutls-6cf6b8f7205adbff41f38320433fb70ea4546720.tar.gz
record: introduce new API functions for early data
This introduces gnutls_record_get_max_early_data_size(), gnutls_record_send_early_data(), and gnutls_record_recv_early_data() functions. Signed-off-by: Daiki Ueno <dueno@redhat.com>
-rw-r--r--doc/Makefile.am6
-rw-r--r--doc/manpages/Makefile.am3
-rw-r--r--lib/ext/early_data.c22
-rw-r--r--lib/includes/gnutls/gnutls.h.in7
-rw-r--r--lib/libgnutls.map8
-rw-r--r--lib/record.c88
-rw-r--r--symbols.last4
7 files changed, 137 insertions, 1 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 130617fa74..b939121898 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1799,6 +1799,8 @@ FUNCS += functions/gnutls_record_get_direction
FUNCS += functions/gnutls_record_get_direction.short
FUNCS += functions/gnutls_record_get_discarded
FUNCS += functions/gnutls_record_get_discarded.short
+FUNCS += functions/gnutls_record_get_max_early_data_size
+FUNCS += functions/gnutls_record_get_max_early_data_size.short
FUNCS += functions/gnutls_record_get_max_size
FUNCS += functions/gnutls_record_get_max_size.short
FUNCS += functions/gnutls_record_get_state
@@ -1807,6 +1809,8 @@ FUNCS += functions/gnutls_record_overhead_size
FUNCS += functions/gnutls_record_overhead_size.short
FUNCS += functions/gnutls_record_recv
FUNCS += functions/gnutls_record_recv.short
+FUNCS += functions/gnutls_record_recv_early_data
+FUNCS += functions/gnutls_record_recv_early_data.short
FUNCS += functions/gnutls_record_recv_packet
FUNCS += functions/gnutls_record_recv_packet.short
FUNCS += functions/gnutls_record_recv_seq
@@ -1815,6 +1819,8 @@ FUNCS += functions/gnutls_record_send
FUNCS += functions/gnutls_record_send.short
FUNCS += functions/gnutls_record_send2
FUNCS += functions/gnutls_record_send2.short
+FUNCS += functions/gnutls_record_send_early_data
+FUNCS += functions/gnutls_record_send_early_data.short
FUNCS += functions/gnutls_record_send_range
FUNCS += functions/gnutls_record_send_range.short
FUNCS += functions/gnutls_record_set_max_early_data_size
diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
index d0544a14d4..9047790c83 100644
--- a/doc/manpages/Makefile.am
+++ b/doc/manpages/Makefile.am
@@ -701,14 +701,17 @@ APIMANS += gnutls_record_disable_padding.3
APIMANS += gnutls_record_discard_queued.3
APIMANS += gnutls_record_get_direction.3
APIMANS += gnutls_record_get_discarded.3
+APIMANS += gnutls_record_get_max_early_data_size.3
APIMANS += gnutls_record_get_max_size.3
APIMANS += gnutls_record_get_state.3
APIMANS += gnutls_record_overhead_size.3
APIMANS += gnutls_record_recv.3
+APIMANS += gnutls_record_recv_early_data.3
APIMANS += gnutls_record_recv_packet.3
APIMANS += gnutls_record_recv_seq.3
APIMANS += gnutls_record_send.3
APIMANS += gnutls_record_send2.3
+APIMANS += gnutls_record_send_early_data.3
APIMANS += gnutls_record_send_range.3
APIMANS += gnutls_record_set_max_early_data_size.3
APIMANS += gnutls_record_set_max_size.3
diff --git a/lib/ext/early_data.c b/lib/ext/early_data.c
index 213e17d5c4..729a528bd7 100644
--- a/lib/ext/early_data.c
+++ b/lib/ext/early_data.c
@@ -92,6 +92,25 @@ early_data_send_params(gnutls_session_t session,
}
/**
+ * gnutls_record_get_max_early_data_size:
+ * @session: is a #gnutls_session_t type.
+ *
+ * This function returns the maximum early data size in this connection.
+ * This property can only be set to servers. The client may be
+ * provided with the maximum allowed size through the "early_data"
+ * extension of the NewSessionTicket handshake message.
+ *
+ * Returns: The maximum early data size in this connection.
+ *
+ * Since: 3.6.5
+ **/
+size_t
+gnutls_record_get_max_early_data_size(gnutls_session_t session)
+{
+ return session->security_parameters.max_early_data_size;
+}
+
+/**
* gnutls_record_set_max_early_data_size:
* @session: is a #gnutls_session_t type.
* @size: is the new size
@@ -113,7 +132,8 @@ gnutls_record_set_max_early_data_size(gnutls_session_t session,
if (session->security_parameters.entity == GNUTLS_CLIENT)
return GNUTLS_E_INVALID_REQUEST;
- if (size > UINT32_MAX)
+ /* Reject zero as well, as it is useless. */
+ if (size == 0 || size > UINT32_MAX)
return GNUTLS_E_INVALID_REQUEST;
session->security_parameters.max_early_data_size = (uint32_t) size;
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index b838ee55dd..0dc173394c 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1436,7 +1436,14 @@ ssize_t gnutls_record_set_max_size(gnutls_session_t session, size_t size);
size_t gnutls_record_check_pending(gnutls_session_t session);
size_t gnutls_record_check_corked(gnutls_session_t session);
+size_t gnutls_record_get_max_early_data_size(gnutls_session_t session);
int gnutls_record_set_max_early_data_size(gnutls_session_t session, size_t size);
+ssize_t gnutls_record_send_early_data(gnutls_session_t session,
+ const void *data,
+ size_t length);
+ssize_t gnutls_record_recv_early_data(gnutls_session_t session,
+ void *data,
+ size_t data_size);
void gnutls_session_force_valid(gnutls_session_t session);
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index ad6613b907..edcfa46575 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1248,6 +1248,14 @@ GNUTLS_3_6_4
gnutls_priority_certificate_type_list2;
} GNUTLS_3_6_3;
+GNUTLS_3_6_5
+{
+ global:
+ gnutls_record_get_max_early_data_size;
+ gnutls_record_send_early_data;
+ gnutls_record_recv_early_data;
+} GNUTLS_3_6_4;
+
GNUTLS_FIPS140_3_4 {
global:
gnutls_cipher_self_test;
diff --git a/lib/record.c b/lib/record.c
index 7dc4f23348..5514ddcef1 100644
--- a/lib/record.c
+++ b/lib/record.c
@@ -2030,6 +2030,94 @@ gnutls_record_send2(gnutls_session_t session, const void *data,
}
/**
+ * gnutls_record_send_early_data:
+ * @session: is a #gnutls_session_t type.
+ * @data: contains the data to send
+ * @data_size: is the length of the data
+ *
+ * This function can be used by a client to send data early in the
+ * handshake processes when resuming a session. This is used to
+ * implement a zero-roundtrip (0-RTT) mode. It has the same semantics
+ * 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.
+ *
+ * Returns: The number of bytes sent, or a negative error code. The
+ * number of bytes sent might be less than @data_size. The maximum
+ * number of bytes this function can send in a single call depends
+ * on the negotiated maximum record size.
+ *
+ * Since: 3.6.5
+ **/
+ssize_t gnutls_record_send_early_data(gnutls_session_t session,
+ const void *data,
+ size_t data_size)
+{
+ int ret;
+
+ if (session->security_parameters.entity != GNUTLS_CLIENT)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ ret =
+ _gnutls_buffer_append_data(&session->internals.
+ early_data_presend_buffer, data,
+ data_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return ret;
+}
+
+/**
+ * gnutls_record_recv_early_data:
+ * @session: is a #gnutls_session_t type.
+ * @data: the buffer that the data will be read into
+ * @data_size: the number of requested bytes
+ *
+ * This function can be used by a searver to retrieve data sent early
+ * in the handshake processes when resuming a session. This is used
+ * to implement a zero-roundtrip (0-RTT) mode. It has the same
+ * semantics as gnutls_record_recv().
+ *
+ * This function can be called either in a handshake hook, or after
+ * the handshake is complete.
+ *
+ * Returns: The number of bytes received and zero when early data
+ * reading is complete. A negative error code is returned in case of
+ * an error. If no early data is received during the handshake, this
+ * function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. The
+ * number of bytes received might be less than the requested
+ * @data_size.
+ *
+ * Since: 3.6.5
+ **/
+ssize_t
+gnutls_record_recv_early_data(gnutls_session_t session, void *data, size_t data_size)
+{
+ mbuffer_st *bufel;
+ gnutls_datum_t msg;
+ size_t length;
+
+ if (session->security_parameters.entity != GNUTLS_SERVER)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ bufel = _mbuffer_head_get_first(&session->internals.early_data_recv_buffer,
+ &msg);
+ if (bufel == NULL)
+ return
+ gnutls_assert_val
+ (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+
+ length = MIN(msg.size, data_size);
+ memcpy(data, msg.data, length);
+ _mbuffer_head_remove_bytes(&session->internals.early_data_recv_buffer,
+ length);
+
+ return length;
+}
+
+/**
* gnutls_record_cork:
* @session: is a #gnutls_session_t type.
*
diff --git a/symbols.last b/symbols.last
index f55663209f..65a578b358 100644
--- a/symbols.last
+++ b/symbols.last
@@ -3,6 +3,7 @@ GNUTLS_3_6_0@GNUTLS_3_6_0
GNUTLS_3_6_2@GNUTLS_3_6_2
GNUTLS_3_6_3@GNUTLS_3_6_3
GNUTLS_3_6_4@GNUTLS_3_6_4
+GNUTLS_3_6_5@GNUTLS_3_6_5
_gnutls_global_init_skip@GNUTLS_3_4
gnutls_aead_cipher_decrypt@GNUTLS_3_4
gnutls_aead_cipher_deinit@GNUTLS_3_4
@@ -677,14 +678,17 @@ gnutls_record_disable_padding@GNUTLS_3_4
gnutls_record_discard_queued@GNUTLS_3_4
gnutls_record_get_direction@GNUTLS_3_4
gnutls_record_get_discarded@GNUTLS_3_4
+gnutls_record_get_max_early_data_size@GNUTLS_3_6_5
gnutls_record_get_max_size@GNUTLS_3_4
gnutls_record_get_state@GNUTLS_3_4
gnutls_record_overhead_size@GNUTLS_3_4
gnutls_record_recv@GNUTLS_3_4
+gnutls_record_recv_early_data@GNUTLS_3_6_5
gnutls_record_recv_packet@GNUTLS_3_4
gnutls_record_recv_seq@GNUTLS_3_4
gnutls_record_send2@GNUTLS_3_6_3
gnutls_record_send@GNUTLS_3_4
+gnutls_record_send_early_data@GNUTLS_3_6_5
gnutls_record_send_range@GNUTLS_3_4
gnutls_record_set_max_early_data_size@GNUTLS_3_6_4
gnutls_record_set_max_size@GNUTLS_3_4