diff options
author | Daiki Ueno <dueno@redhat.com> | 2018-10-12 13:34:21 +0200 |
---|---|---|
committer | Daiki Ueno <dueno@redhat.com> | 2018-11-11 07:03:44 +0100 |
commit | 6cf6b8f7205adbff41f38320433fb70ea4546720 (patch) | |
tree | 53020c29200ff4b65804b4f10122ecc7f4da68df | |
parent | 957f7537604b21653c0d456e55fabed600052508 (diff) | |
download | gnutls-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.am | 6 | ||||
-rw-r--r-- | doc/manpages/Makefile.am | 3 | ||||
-rw-r--r-- | lib/ext/early_data.c | 22 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 7 | ||||
-rw-r--r-- | lib/libgnutls.map | 8 | ||||
-rw-r--r-- | lib/record.c | 88 | ||||
-rw-r--r-- | symbols.last | 4 |
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 |