ecv_params’ function is responsible for parsing incoming extension data (both in the client and server). The ‘_gnutls_foobar_send_params’ function is responsible for formatting extension data such that it can be send over the wire (both in the client and server). It should append data to provided buffer and return a positive (or zero) number on success or a negative error code. Previous to 3.6.0 versions of GnuTLS required that function to return the number of bytes that were written. If zero is returned and no bytes are appended the extension will not be sent. If a zero byte extension is to be sent this function must return ‘GNUTLS_E_INT_RET_0’. If you receive length fields that don't match, return ‘GNUTLS_E_UNEXPECTED_PACKET_LENGTH’. If you receive invalid data, return ‘GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER’. You can use other error codes from the list in *note Error codes::. Return 0 on success. An extension typically stores private information in the ‘session’ data for later usage. That can be done using the functions ‘_gnutls_hello_ext_set_datum’ and ‘_gnutls_hello_ext_get_datum’. You can check simple examples at ‘lib/ext/max_record.c’ and ‘lib/ext/server_name.c’ extensions. That private information can be saved and restored across session resumption if the following functions are set: The ‘_gnutls_foobar_pack’ function is responsible for packing internal extension data to save them in the session resumption storage. The ‘_gnutls_foobar_unpack’ function is responsible for restoring session data from the session resumption storage. When the internal data is stored using the ‘_gnutls_hello_ext_set_datum’, then you can rely on the default pack and unpack functions: ‘_gnutls_hello_ext_default_pack’ and ‘_gnutls_hello_ext_default_unpack’. Recall that both for the client and server, the send and receive functions most likely will need to do different things depending on which mode they are in. It may be useful to make this distinction explicit in the code. Thus, for example, a better template than above would be: int _gnutls_foobar_recv_params (gnutls_session_t session, const uint8_t * data, size_t data_size) { if (session->security_parameters.entity == GNUTLS_CLIENT) return foobar_recv_client (session, data, data_size); else return foobar_recv_server (session, data, data_size); } int _gnutls_foobar_send_params (gnutls_session_t session, gnutls_buffer_st * data) { if (session->security_parameters.entity == GNUTLS_CLIENT) return foobar_send_client (session, data); else return foobar_send_server (session, data); } The functions used would be declared as ‘static’ functions, of the appropriate prototype, in the same file. When adding the new extension files, you'll need to add them to ‘lib/ext/Makefile.am’ as well, for example: if ENABLE_FOOBAR libgnutls_ext_la_SOURCES += ext/foobar.c ext/foobar.h endif Add API functions to use the extension. ....................................... It might be desirable to allow users of the extension to request the use of the extension, or set extension specific data. This can be implemented by adding extension specific function calls that can be added to ‘includes/gnutls/gnutls.h’, as long as the LGPLv2.1+ applies. The implementation of these functions should lie in the ‘lib/ext/foobar.c’ file. To make the API available in the shared library you need to add the added symbols in ‘lib/libgnutls.map’, so that the symbols are exported properly. When writing GTK-DOC style documentation for your new APIs, don't forget to add ‘Since:’ tags to indicate the GnuTLS version the API was introduced in. Adding a new Supplemental Data Handshake Message ------------------------------------------------ TLS handshake extensions allow to send so called supplemental data handshake messages [*note RFC4680::]. This short section explains how to implement a supplemental data handshake message for a given TLS extension. First of all, modify your extension ‘foobar’ in the way, to instruct the handshake process to send and receive supplemental data, as shown below. int _gnutls_foobar_recv_params (gnutls_session_t session, const opaque * data, size_t _data_size) { ... gnutls_supplemental_recv(session, 1); ... } int _gnutls_foobar_send_params (gnutls_session_t session, gnutls_buffer_st *extdata) { ... gnutls_supplemental_send(session, 1); ... } Furthermore you'll need two new functions ‘_foobar_supp_recv_params’ and ‘_foobar_supp_send_params’, which must conform to the following prototypes. typedef int (*gnutls_supp_recv_func)(gnutls_session_t session, const unsigned char *data, size_t data_size); typedef int (*gnutls_supp_send_func)(gnutls_session_t session, gnutls_buffer_t buf); The following example code shows how to send a "Hello World" string in the supplemental data handshake message. int _foobar_supp_recv_params(gnutls_session_t session, const opaque *data, size_t _data_size) { uint8_t len = _data_size; unsigned char *msg; msg = gnutls_malloc(len); if (msg == NULL) return GNUTLS_E_MEMORY_ERROR; memcpy(msg, data, len); msg[len]='\0'; /* do something with msg */ gnutls_free(msg); return len; } int _foobar_supp_send_params(gnutls_session_t session, gnutls_buffer_t buf) { unsigned char *msg = "hello world"; int len = strlen(msg); if (gnutls_buffer_append_data(buf, msg, len) < 0) abort(); return len; } Afterwards, register the new supplemental data using *note gnutls_session_supplemental_register::, or *note gnutls_supplemental_register:: at some point in your program.