diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c
index 36ac43e..ca47a46 100644
--- a/lib/gnutls_extensions.c
+++ b/lib/gnutls_extensions.c
@@ -307,75 +307,75 @@ int _gnutls_ext_init(void)
 {
 	int ret;
 
-	ret = _gnutls_ext_register(&ext_mod_max_record_size);
+	ret = gnutls_ext_register(&ext_mod_max_record_size);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 
 #ifdef ENABLE_OCSP
-	ret = _gnutls_ext_register(&ext_mod_status_request);
+	ret = gnutls_ext_register(&ext_mod_status_request);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 #endif
 
 #ifdef ENABLE_OPENPGP
-	ret = _gnutls_ext_register(&ext_mod_cert_type);
+	ret = gnutls_ext_register(&ext_mod_cert_type);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 #endif
 
-	ret = _gnutls_ext_register(&ext_mod_server_name);
+	ret = gnutls_ext_register(&ext_mod_server_name);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 
-	ret = _gnutls_ext_register(&ext_mod_sr);
+	ret = gnutls_ext_register(&ext_mod_sr);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 
 #ifdef ENABLE_SRP
-	ret = _gnutls_ext_register(&ext_mod_srp);
+	ret = gnutls_ext_register(&ext_mod_srp);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 #endif
 
 #ifdef ENABLE_HEARTBEAT
-	ret = _gnutls_ext_register(&ext_mod_heartbeat);
+	ret = gnutls_ext_register(&ext_mod_heartbeat);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 #endif
 
 #ifdef ENABLE_SESSION_TICKETS
-	ret = _gnutls_ext_register(&ext_mod_session_ticket);
+	ret = gnutls_ext_register(&ext_mod_session_ticket);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 #endif
 
-	ret = _gnutls_ext_register(&ext_mod_supported_ecc);
+	ret = gnutls_ext_register(&ext_mod_supported_ecc);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 
-	ret = _gnutls_ext_register(&ext_mod_supported_ecc_pf);
+	ret = gnutls_ext_register(&ext_mod_supported_ecc_pf);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 
-	ret = _gnutls_ext_register(&ext_mod_sig);
+	ret = gnutls_ext_register(&ext_mod_sig);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 
 #ifdef ENABLE_DTLS_SRTP
-	ret = _gnutls_ext_register(&ext_mod_srtp);
+	ret = gnutls_ext_register(&ext_mod_srtp);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 #endif
 
 #ifdef ENABLE_ALPN
-	ret = _gnutls_ext_register(&ext_mod_alpn);
+	ret = gnutls_ext_register(&ext_mod_alpn);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 #endif
 
 	/* This must be the last extension registered.
 	 */
-	ret = _gnutls_ext_register(&ext_mod_dumbfw);
+	ret = gnutls_ext_register(&ext_mod_dumbfw);
 	if (ret != GNUTLS_E_SUCCESS)
 		return ret;
 
@@ -389,7 +389,7 @@ void _gnutls_ext_deinit(void)
 	extfunc_size = 0;
 }
 
-int _gnutls_ext_register(extension_entry_st * mod)
+int gnutls_ext_register(extension_entry_st * mod)
 {
 	extension_entry_st *p;
 
diff --git a/lib/gnutls_extensions.h b/lib/gnutls_extensions.h
index 11c0faf..7c56baf 100644
--- a/lib/gnutls_extensions.h
+++ b/lib/gnutls_extensions.h
@@ -23,13 +23,7 @@
 #ifndef GNUTLS_EXTENSIONS_H
 #define GNUTLS_EXTENSIONS_H
 
-#include <gnutls_str.h>
-
-typedef int (*gnutls_ext_recv_func) (gnutls_session_t session,
-				     const unsigned char *data,
-				     size_t len);
-typedef int (*gnutls_ext_send_func) (gnutls_session_t session,
-				     gnutls_buffer_st * extdata);
+#include <gnutls/gnutls.h>
 
 int _gnutls_parse_extensions(gnutls_session_t session,
 			     gnutls_ext_parse_type_t parse_type,
@@ -42,13 +36,6 @@ void _gnutls_ext_deinit(void);
 
 void _gnutls_extension_list_add(gnutls_session_t session, uint16_t type);
 
-typedef void (*gnutls_ext_deinit_data_func) (extension_priv_data_t data);
-typedef int (*gnutls_ext_pack_func) (extension_priv_data_t data,
-				     gnutls_buffer_st * packed_data);
-typedef int (*gnutls_ext_unpack_func) (gnutls_buffer_st * packed_data,
-				       extension_priv_data_t * data);
-typedef int (*gnutls_ext_epoch_func) (gnutls_session_t session);
-
 void _gnutls_ext_free_session_data(gnutls_session_t session);
 
 /* functions to be used by extensions internally
@@ -70,33 +57,4 @@ int _gnutls_ext_before_epoch_change(gnutls_session_t session);
 int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st * packed);
 int _gnutls_ext_unpack(gnutls_session_t session,
 		       gnutls_buffer_st * packed);
-
-typedef struct {
-	const char *name;
-	uint16_t type;
-	gnutls_ext_parse_type_t parse_type;
-
-	/* this function must return 0 when Not Applicable
-	 * size of extension data if ok
-	 * < 0 on other error.
-	 */
-	gnutls_ext_recv_func recv_func;
-
-	/* this function must return 0 when Not Applicable
-	 * size of extension data if ok
-	 * GNUTLS_E_INT_RET_0 if extension data size is zero
-	 * < 0 on other error.
-	 */
-	gnutls_ext_send_func send_func;
-
-	gnutls_ext_deinit_data_func deinit_func;	/* this will be called to deinitialize
-							 * internal data 
-							 */
-	gnutls_ext_pack_func pack_func;	/* packs internal data to machine independent format */
-	gnutls_ext_unpack_func unpack_func;	/* unpacks internal data */
-	gnutls_ext_epoch_func epoch_func;	/* called after the handshake is finished */
-} extension_entry_st;
-
-int _gnutls_ext_register(extension_entry_st *);
-
 #endif
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 942ec32..8abe5c9 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -142,29 +142,6 @@ typedef struct {
  */
 #define MAX_EXT_TYPES 32
 
-  /**
-   * gnutls_ext_parse_type_t:
-   * @GNUTLS_EXT_NONE: Never parsed
-   * @GNUTLS_EXT_ANY: Any extension type.
-   * @GNUTLS_EXT_APPLICATION: Application extension.
-   * @GNUTLS_EXT_TLS: TLS-internal extension.
-   * @GNUTLS_EXT_MANDATORY: Extension parsed even if resuming (or extensions are disabled).
-   *
-   * Enumeration of different TLS extension types.  This flag
-   * indicates for an extension whether it is useful to application
-   * level or TLS level only.  This is (only) used to parse the
-   * application level extensions before the "client_hello" callback
-   * is called.
-   */
-typedef enum {
-	GNUTLS_EXT_ANY = 0,
-	GNUTLS_EXT_APPLICATION = 1,
-	GNUTLS_EXT_TLS = 2,
-	GNUTLS_EXT_MANDATORY = 3,
-	GNUTLS_EXT_NONE = 4
-} gnutls_ext_parse_type_t;
-
-
 /* expire time for resuming sessions */
 #define DEFAULT_EXPIRE_TIME 3600
 
@@ -744,11 +721,6 @@ typedef struct {
 	unsigned int packets_dropped;
 } dtls_st;
 
-typedef union {
-	void *ptr;
-	uint32_t num;
-} extension_priv_data_t;
-
 typedef struct {
 	/* holds all the parsed data received by the record layer */
 	mbuffer_head_st record_buffer;
diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c
index e820723..b724963 100644
--- a/lib/gnutls_str.c
+++ b/lib/gnutls_str.c
@@ -107,6 +107,12 @@ void _gnutls_buffer_clear(gnutls_buffer_st * str)
 #define MIN_CHUNK 1024
 
 int
+gnutls_buffer_append_data(gnutls_buffer_st * dest, const void *data, size_t data_size)
+{
+	return _gnutls_buffer_append_data(dest, data, data_size);
+}
+
+int
 _gnutls_buffer_append_data(gnutls_buffer_st * dest, const void *data,
 			   size_t data_size)
 {
diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h
index bc9d8bd..67623d4 100644
--- a/lib/gnutls_str.h
+++ b/lib/gnutls_str.h
@@ -33,7 +33,7 @@ void _gnutls_mem_cpy(char *dest, size_t dest_tot_size, const char *src,
 		     size_t src_size);
 void _gnutls_str_cat(char *dest, size_t dest_tot_size, const char *src);
 
-typedef struct {
+typedef struct gnutls_buffer{
 	uint8_t *allocd;	/* pointer to allocated data */
 	uint8_t *data;		/* API: pointer to data to copy from */
 	size_t max_length;
diff --git a/lib/gnutls_supplemental.c b/lib/gnutls_supplemental.c
index 56ca1e9..d6cf722 100644
--- a/lib/gnutls_supplemental.c
+++ b/lib/gnutls_supplemental.c
@@ -43,26 +43,14 @@
  * want to send any data, it is fine to return without doing anything.
  */
 
+#include <gnutls/gnutls.h>
 #include "gnutls_int.h"
 #include "gnutls_supplemental.h"
 #include "gnutls_errors.h"
 #include "gnutls_num.h"
 
-typedef int (*supp_recv_func) (gnutls_session_t session,
-			       const uint8_t * data, size_t data_size);
-typedef int (*supp_send_func) (gnutls_session_t session,
-			       gnutls_buffer_st * buf);
-
-typedef struct {
-	const char *name;
-	gnutls_supplemental_data_format_type_t type;
-	supp_recv_func supp_recv_func;
-	supp_send_func supp_send_func;
-} gnutls_supplemental_entry;
-
-gnutls_supplemental_entry _gnutls_supplemental[] = {
-	{0, 0, 0, 0}
-};
+static size_t suppfunc_size = 0;
+static gnutls_supplemental_entry *suppfunc = NULL;
 
 /**
  * gnutls_supplemental_get_name:
@@ -78,11 +66,12 @@ const char
     *gnutls_supplemental_get_name(gnutls_supplemental_data_format_type_t
 				  type)
 {
-	gnutls_supplemental_entry *p;
+	size_t i;
 
-	for (p = _gnutls_supplemental; p->name != NULL; p++)
-		if (p->type == type)
-			return p->name;
+	for (i = 0; i < suppfunc_size; i++) {
+		if (suppfunc[i].type == type)
+			return suppfunc[i].name;
+	}
 
 	return NULL;
 }
@@ -90,11 +79,12 @@ const char
 static supp_recv_func
 get_supp_func_recv(gnutls_supplemental_data_format_type_t type)
 {
-	gnutls_supplemental_entry *p;
+	size_t i;
 
-	for (p = _gnutls_supplemental; p->name != NULL; p++)
-		if (p->type == type)
-			return p->supp_recv_func;
+	for (i = 0; i < suppfunc_size; i++) {
+		if (suppfunc[i].type == type)
+			return suppfunc[i].supp_recv_func;
+	}
 
 	return NULL;
 }
@@ -102,6 +92,7 @@ get_supp_func_recv(gnutls_supplemental_data_format_type_t type)
 int
 _gnutls_gen_supplemental(gnutls_session_t session, gnutls_buffer_st * buf)
 {
+	size_t i;
 	gnutls_supplemental_entry *p;
 	int ret;
 
@@ -112,7 +103,8 @@ _gnutls_gen_supplemental(gnutls_session_t session, gnutls_buffer_st * buf)
 		return ret;
 	}
 
-	for (p = _gnutls_supplemental; p->name; p++) {
+	for (i = 0; i < suppfunc_size; i++) {
+		p = &suppfunc[i];
 		supp_send_func supp_send = p->supp_send_func;
 		size_t sizepos = buf->length;
 
@@ -131,8 +123,8 @@ _gnutls_gen_supplemental(gnutls_session_t session, gnutls_buffer_st * buf)
 
 		/* If data were added, store type+length, otherwise reset. */
 		if (buf->length > sizepos + 4) {
-			buf->data[sizepos] = 0;
-			buf->data[sizepos + 1] = p->type;
+			buf->data[sizepos] = (p->type >> 8) & 0xFF;
+			buf->data[sizepos + 1] = (p->type) & 0xFF;
 			buf->data[sizepos + 2] =
 			    ((buf->length - sizepos - 4) >> 8) & 0xFF;
 			buf->data[sizepos + 3] =
@@ -205,3 +197,36 @@ _gnutls_parse_supplemental(gnutls_session_t session,
 
 	return 0;
 }
+
+int
+gnutls_supplemental_register(gnutls_supplemental_entry *entry)
+{
+	gnutls_supplemental_entry *p;
+
+	p = gnutls_realloc_fast(suppfunc,
+				sizeof(*suppfunc) * (suppfunc_size + 1));
+	if (!p) {
+		gnutls_assert();
+		return GNUTLS_E_MEMORY_ERROR;
+	}
+
+	suppfunc = p;
+
+	memcpy(&suppfunc[suppfunc_size], entry, sizeof(*entry));
+
+	suppfunc_size++;
+
+	return GNUTLS_E_SUCCESS;
+}
+
+void
+gnutls_do_recv_supplemental(gnutls_session_t session, int do_recv_supplemental)
+{
+	session->security_parameters.do_recv_supplemental = do_recv_supplemental;
+}
+
+void
+gnutls_do_send_supplemental(gnutls_session_t session, int do_send_supplemental)
+{
+	session->security_parameters.do_send_supplemental = do_send_supplemental;
+}
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index addc3ab..c4b5403 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1030,9 +1030,7 @@ int gnutls_safe_renegotiation_status(gnutls_session_t session);
  *
  * Enumeration of different supplemental data types (RFC 4680).
  */
-typedef enum {
-	GNUTLS_SUPPLEMENTAL_USER_MAPPING_DATA = 0
-} gnutls_supplemental_data_format_type_t;
+typedef short gnutls_supplemental_data_format_type_t;
 
 const char
 *gnutls_supplemental_get_name(gnutls_supplemental_data_format_type_t type);
@@ -2146,6 +2144,109 @@ void gnutls_certificate_set_pin_function(gnutls_certificate_credentials_t,
 					 gnutls_pin_callback_t fn,
 					 void *userdata);
 
+
+/* Public string related functions */
+typedef struct gnutls_buffer gnutls_buffer_st;
+
+int gnutls_buffer_append_data(gnutls_buffer_st *, const void *data, size_t data_size);
+
+/* Public extensions related functions */
+
+typedef union {
+	void *ptr;
+	int num;
+} extension_priv_data_t;
+
+typedef int (*gnutls_ext_recv_func) (gnutls_session_t session,
+					 const unsigned char *data,
+					 size_t len);
+
+typedef int (*gnutls_ext_send_func) (gnutls_session_t session,
+					 gnutls_buffer_st * extdata);
+
+typedef void (*gnutls_ext_deinit_data_func) (extension_priv_data_t data);
+
+typedef int (*gnutls_ext_pack_func) (extension_priv_data_t data,
+					 gnutls_buffer_st * packed_data);
+
+typedef int (*gnutls_ext_unpack_func) (gnutls_buffer_st * packed_data,
+					   extension_priv_data_t * data);
+
+typedef int (*gnutls_ext_epoch_func) (gnutls_session_t session);
+
+/**
+ * gnutls_ext_parse_type_t:
+ * @GNUTLS_EXT_NONE: Never parsed
+ * @GNUTLS_EXT_ANY: Any extension type.
+ * @GNUTLS_EXT_APPLICATION: Application extension.
+ * @GNUTLS_EXT_TLS: TLS-internal extension.
+ * @GNUTLS_EXT_MANDATORY: Extension parsed even if resuming (or extensions are disabled).
+ *
+ * Enumeration of different TLS extension types.  This flag
+ * indicates for an extension whether it is useful to application
+ * level or TLS level only.  This is (only) used to parse the
+ * application level extensions before the "client_hello" callback
+ * is called.
+ */
+typedef enum {
+  GNUTLS_EXT_ANY = 0,
+  GNUTLS_EXT_APPLICATION = 1,
+  GNUTLS_EXT_TLS = 2,
+  GNUTLS_EXT_MANDATORY = 3,
+  GNUTLS_EXT_NONE = 4
+} gnutls_ext_parse_type_t;
+
+typedef struct {
+	const char *name;
+	short type;
+	gnutls_ext_parse_type_t parse_type;
+
+	/* this function must return 0 when Not Applicable
+	 * size of extension data if ok
+	 * < 0 on other error.
+	 */
+	gnutls_ext_recv_func recv_func;
+
+	/* this function must return 0 when Not Applicable
+	 * size of extension data if ok
+	 * GNUTLS_E_INT_RET_0 if extension data size is zero
+	 * < 0 on other error.
+	 */
+	gnutls_ext_send_func send_func;
+
+	gnutls_ext_deinit_data_func deinit_func;	/* this will be called to deinitialize
+							 * internal data
+							 */
+	gnutls_ext_pack_func pack_func;	/* packs internal data to machine independent format */
+	gnutls_ext_unpack_func unpack_func;	/* unpacks internal data */
+	gnutls_ext_epoch_func epoch_func;	/* called after the handshake is finished */
+} extension_entry_st;
+
+	/* Register a custom tls extension
+	 */
+int gnutls_ext_register(extension_entry_st *);
+
+/* Public supplemental data related functions */
+
+typedef int (*supp_recv_func) (gnutls_session_t session,
+			       const unsigned char * data, size_t data_size);
+typedef int (*supp_send_func) (gnutls_session_t session,
+			       gnutls_buffer_st * buf);
+
+typedef struct {
+	const char *name;
+	gnutls_supplemental_data_format_type_t type;
+	supp_recv_func supp_recv_func;
+	supp_send_func supp_send_func;
+} gnutls_supplemental_entry;
+
+
+int gnutls_supplemental_register(gnutls_supplemental_entry *);
+
+void gnutls_do_recv_supplemental(gnutls_session_t session, int do_recv_supplemental);
+
+void gnutls_do_send_supplemental(gnutls_session_t session, int do_send_supplemental);
+
 /* FIPS140-2 related functions */
 int gnutls_fips140_mode_enabled(void);
 
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 6e56004..4e8abcd 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1024,6 +1024,11 @@ GNUTLS_3_1_0 {
 	gnutls_x509_ext_deinit;
 	gnutls_x509_ext_print;
 	gnutls_x509_othername_to_virtual;
+	gnutls_supplemental_register;
+ 	gnutls_do_recv_supplemental;
+	gnutls_do_send_supplemental;
+	gnutls_ext_register;
+	gnutls_buffer_append_data;
 } GNUTLS_3_0_0;
 
 GNUTLS_FIPS140 {
