** libgnutls: Simplified the DTLS sliding window implementation.
+** libgnutls: Added the gnutls_sbuf_t structure and accompanying
+functions to enable buffering in sending application data.
+
** libgnutls: Added %RANDOM_PADDING priority string. It enables a new
random padding mechanism in TLS allowing random padding in TLS records
in all ciphersuites. Both the server and the client must support this
** API and ABI modifications:
gnutls_record_get_random_padding_status: Added
+gnutls_sbuf_deinit: Added
+gnutls_sbuf_init: Added
+gnutls_sbuf_flush: Added
+gnutls_sbuf_queue: Added
* Version 3.1.6 (released 2013-01-02)
* Setting up the transport layer::
* TLS handshake::
* Data transfer and termination::
+* Buffered data transfer::
* Handling alerts::
* Priority Strings::
* Selecting cryptographic key sizes::
@showfuncdesc{gnutls_bye}
@showfuncdesc{gnutls_deinit}
+@node Buffered data transfer
+@section Buffered data transfer
+
+Although @funcref{gnutls_record_send} is sufficient to transmit data
+to the peer, when many small chunks of data are to be transmitted
+it is inefficient and wastes bandwidth due to the TLS record
+overhead. In that case it is preferrable to combine the small chunks
+before transmission. The @emph{gnutls_sbuf} interface is a helper interface
+that provides that functionality.
+
+@showfuncdesc{gnutls_sbuf_init}
+
+@showfuncdesc{gnutls_sbuf_queue}
+
+@showfuncB{gnutls_sbuf_flush,gnutls_sbuf_deinit}
+
+
@node Handling alerts
@section Handling alerts
During a TLS connection alert messages may be exchanged by the
gnutls_rsa_export.c gnutls_helper.c gnutls_supplemental.c \
random.c crypto-api.c gnutls_privkey.c gnutls_pcert.c \
gnutls_pubkey.c locks.c gnutls_dtls.c system_override.c \
- crypto-backend.c verify-tofu.c pin.c tpm.c
+ crypto-backend.c verify-tofu.c pin.c tpm.c sbuf.c
if ENABLE_PKCS11
COBJECTS += pkcs11.c pkcs11_privkey.c pkcs11_write.c pkcs11_secret.c
void gnutls_certificate_set_pin_function (gnutls_certificate_credentials_t,
gnutls_pin_callback_t fn, void *userdata);
+/* Buffered session I/O */
+typedef struct gnutls_sbuf_st *gnutls_sbuf_t;
+
+ssize_t gnutls_sbuf_queue (gnutls_sbuf_t sb, const void *data,
+ size_t data_size);
+
+ssize_t gnutls_sbuf_flush (gnutls_sbuf_t sb);
+
+#define GNUTLS_SBUF_QUEUE_FLUSHES 1
+int gnutls_sbuf_init (gnutls_sbuf_t * sb, gnutls_session_t session,
+ unsigned int flags);
+void gnutls_sbuf_deinit(gnutls_sbuf_t sb);
+
/* Gnutls error codes. The mapping to a TLS alert is also shown in
* comments.
gnutls_pubkey_import_x509_crq;
gnutls_pubkey_print;
gnutls_record_get_random_padding_status;
+ gnutls_sbuf_deinit;
+ gnutls_sbuf_init;
+ gnutls_sbuf_flush;
+ gnutls_sbuf_queue;
} GNUTLS_3_0_0;
GNUTLS_PRIVATE {
--- /dev/null
+/*
+ * Copyright (C) 2013 Nikos Mavrogiannopoulos
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The libdane library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+#include <gnutls_str.h>
+
+struct gnutls_sbuf_st {
+ gnutls_session_t session;
+ gnutls_buffer_st buf;
+ unsigned int flags;
+};
+
+/**
+ * gnutls_init:
+ * @isb: is a pointer to a #gnutls_sbuf_t structure.
+ * @session: a GnuTLS session
+ * @flags: should be zero or %GNUTLS_SBUF_QUEUE_FLUSHES
+ *
+ * This function initializes a #gnutls_sbuf_t structure associated
+ * with the provided session. If the flag %GNUTLS_SBUF_QUEUE_FLUSHES
+ * is set then gnutls_sbuf_queue() will flush when the maximum
+ * data size for a record is reached.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
+ *
+ * Since: 3.1.7
+ **/
+int gnutls_sbuf_init (gnutls_sbuf_t * isb, gnutls_session_t session,
+ unsigned int flags)
+{
+struct gnutls_sbuf_st* sb;
+
+ sb = gnutls_malloc(sizeof(*sb));
+ if (sb == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ _gnutls_buffer_init(&sb->buf);
+ sb->session = session;
+ sb->flags = flags;
+
+ *isb = sb;
+
+ return 0;
+}
+
+/**
+ * gnutls_sbuf_deinit:
+ * @sb: is a #gnutls_sbuf_t structure.
+ *
+ * This function clears all buffers associated with the @sb
+ * structure. The GnuTLS session associated with the structure
+ * is left intact.
+ *
+ * Since: 3.1.7
+ **/
+void gnutls_sbuf_deinit(gnutls_sbuf_t sb)
+{
+ _gnutls_buffer_clear(&sb->buf);
+ gnutls_free(sb);
+}
+
+/**
+ * gnutls_sbuf_queue:
+ * @sb: is a #gnutls_sbuf_t structure.
+ * @data: contains the data to send
+ * @data_size: is the length of the data
+ *
+ * This function is the buffered equivalent of gnutls_record_send().
+ * Instead of sending the data immediately the data are buffered
+ * until gnutls_sbuf_queue() is called, or if the flag %GNUTLS_SBUF_QUEUE_FLUSHES
+ * is set, until the number of bytes for a full record is reached.
+ *
+ * This function must only be used with blocking sockets.
+ *
+ * Returns: On success, if no data were sent then zero is returned, otherwise the
+ * number of bytes sent. If an error occurs a negative error code is returned.
+ *
+ * Since: 3.1.7
+ **/
+ssize_t gnutls_sbuf_queue (gnutls_sbuf_t sb, const void *data,
+ size_t data_size)
+{
+int ret;
+
+ ret = _gnutls_buffer_append_data(&sb->buf, data, data_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ if ((sb->flags & GNUTLS_SBUF_QUEUE_FLUSHES) &&
+ sb->buf.length >= MAX_RECORD_SEND_SIZE(sb->session))
+ {
+ do
+ {
+ ret = gnutls_record_send(sb->session, sb->buf.data, sb->buf.length);
+ }
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ sb->buf.data += ret;
+ sb->buf.length -= ret;
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_sbuf_flush:
+ * @sb: is a #gnutls_sbuf_t structure.
+ *
+ * This function flushes the buffer @sb. All the data stored are transmitted.
+ *
+ * This function must only be used with blocking sockets.
+ *
+ * Returns: On success, the number of bytes sent, otherwise a negative error code.
+ *
+ * Since: 3.1.7
+ **/
+ssize_t gnutls_sbuf_flush (gnutls_sbuf_t sb)
+{
+int ret;
+ssize_t total = 0;
+
+ while(sb->buf.length > 0)
+ {
+ do
+ {
+ ret = gnutls_record_send(sb->session, sb->buf.data, sb->buf.length);
+ }
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ sb->buf.data += ret;
+ sb->buf.length -= ret;
+ total += ret;
+ }
+
+ return total;
+}
mini-termination mini-x509-cas mini-x509-2 pkcs12_simple \
mini-emsgsize-dtls mini-handshake-timeout chainverify-unsorted \
mini-dtls-heartbeat mini-x509-callbacks key-openssl \
- mini-dtls-srtp mini-dtls-record
+ mini-dtls-srtp mini-dtls-record mini-sbuf
if ENABLE_OCSP
ctests += ocsp
--- /dev/null
+/*
+ * Copyright (C) 2008-2012 Free Software Foundation, Inc.
+ *
+ * Author: Simon Josefsson
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include "eagain-common.h"
+
+#include "utils.h"
+
+const char* side = "";
+
+static void
+tls_log_func (int level, const char *str)
+{
+ fprintf (stderr, "%s|<%d>| %s", side, level, str);
+}
+
+#define MAX_BUF 60*1024
+
+static unsigned char server_buf[MAX_BUF];
+static unsigned char client_buf[MAX_BUF];
+
+void
+doit (void)
+{
+ /* Server stuff. */
+ gnutls_anon_server_credentials_t s_anoncred;
+ const gnutls_datum_t p3 = { (unsigned char *) pkcs3, strlen (pkcs3) };
+ static gnutls_dh_params_t dh_params;
+ gnutls_session_t server;
+ gnutls_sbuf_t ssbuf;
+ int sret = GNUTLS_E_AGAIN;
+ /* Client stuff. */
+ gnutls_anon_client_credentials_t c_anoncred;
+ gnutls_session_t client;
+ int cret = GNUTLS_E_AGAIN;
+ /* Need to enable anonymous KX specifically. */
+ int ret;
+ ssize_t left, spos, cpos;
+
+ /* General init. */
+ gnutls_global_init ();
+ gnutls_global_set_log_function (tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level (4711);
+
+ /* Init server */
+ gnutls_anon_allocate_server_credentials (&s_anoncred);
+ gnutls_dh_params_init (&dh_params);
+ gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
+ gnutls_anon_set_server_dh_params (s_anoncred, dh_params);
+ gnutls_init (&server, GNUTLS_SERVER);
+ gnutls_priority_set_direct (server, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL);
+ gnutls_credentials_set (server, GNUTLS_CRD_ANON, s_anoncred);
+ gnutls_dh_set_prime_bits (server, 1024);
+ gnutls_transport_set_push_function (server, server_push);
+ gnutls_transport_set_pull_function (server, server_pull);
+ gnutls_transport_set_ptr (server, (gnutls_transport_ptr_t)server);
+
+ gnutls_sbuf_init(&ssbuf, server, GNUTLS_SBUF_QUEUE_FLUSHES);
+
+ gnutls_rnd(GNUTLS_RND_NONCE, server_buf, sizeof(server_buf));
+
+ /* Init client */
+ gnutls_anon_allocate_client_credentials (&c_anoncred);
+ gnutls_init (&client, GNUTLS_CLIENT);
+ gnutls_priority_set_direct (client, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL);
+ gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred);
+ gnutls_transport_set_push_function (client, client_push);
+ gnutls_transport_set_pull_function (client, client_pull);
+ gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t)client);
+
+ memset(client_buf, 0, sizeof(client_buf));
+
+ HANDSHAKE(client, server);
+
+ if (debug)
+ success ("Handshake established\n");
+
+#define SEND_SIZE 100
+ left = sizeof(server_buf);
+ spos = 0;
+ cpos = 0;
+ while (left > 0)
+ {
+ if (left > SEND_SIZE)
+ {
+ ret = gnutls_sbuf_queue(ssbuf, server_buf+spos, SEND_SIZE);
+ left -= SEND_SIZE;
+ spos += SEND_SIZE;
+ }
+ else
+ {
+ gnutls_sbuf_queue(ssbuf, server_buf+spos, left);
+ ret = gnutls_sbuf_flush(ssbuf);
+ left = 0;
+ }
+
+ if (ret < 0)
+ {
+ fail("Error sending\n");
+ abort();
+ }
+
+ if (ret > 0)
+ { /* received in client side */
+ ret = gnutls_record_recv(client, client_buf+cpos, sizeof(client_buf)-cpos);
+ if (ret > 0)
+ cpos += ret;
+
+ if (ret < 0)
+ {
+ fail("Error sending\n");
+ abort();
+ }
+ }
+ }
+
+ if (memcmp(client_buf, server_buf, sizeof(server_buf)) != 0)
+ {
+ fail("Data do not match!\n");
+ abort();
+ }
+
+ gnutls_bye (client, GNUTLS_SHUT_RDWR);
+ gnutls_bye (server, GNUTLS_SHUT_RDWR);
+
+ gnutls_deinit (client);
+ gnutls_deinit (server);
+
+ gnutls_anon_free_client_credentials (c_anoncred);
+ gnutls_anon_free_server_credentials (s_anoncred);
+
+ gnutls_dh_params_deinit (dh_params);
+
+ gnutls_global_deinit ();
+}