gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_2_9_10-220-ga9b55a4


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_9_10-220-ga9b55a4
Date: Sun, 13 Jun 2010 19:46:21 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=a9b55a42fa65e37fbd00c7359f56b11eaea11e3e

The branch, master has been updated
       via  a9b55a42fa65e37fbd00c7359f56b11eaea11e3e (commit)
       via  6affb75709b91ea172d6119ecb687a767a9423ae (commit)
       via  75daeac5cdd19a57053d45f267fadfbb034a93be (commit)
      from  f8c6a0c9bf202c338088c36d3463958119b1f50e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a9b55a42fa65e37fbd00c7359f56b11eaea11e3e
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri Jun 11 20:17:33 2010 +0200

    Simplified and made more safe the packing of data for session storage. 
Extensions use
    the internal API to store/retrieve during resumption.
    
    Removed OPRFI since it was never standardized and was never actually 
included in gnutls
    since it was in inactive ifdef. This was instead of rewriting it to use the 
new API.

commit 6affb75709b91ea172d6119ecb687a767a9423ae
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri Jun 11 15:01:00 2010 +0200

    The gnutls_string code was simplified and integrated with the buffer to 
avoid
    having two named for the same thing.

commit 75daeac5cdd19a57053d45f267fadfbb034a93be
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri Jun 11 14:46:16 2010 +0200

    Properly handle fork() case.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                             |    4 +
 doc/cha-gtls-app.texi            |   15 -
 lib/auth_srp.c                   |   46 ++-
 lib/ext_cert_type.c              |   23 +-
 lib/ext_cert_type.h              |   15 +-
 lib/ext_max_record.c             |  159 ++++++-
 lib/ext_max_record.h             |   17 +-
 lib/ext_oprfi.c                  |  254 ----------
 lib/ext_oprfi.h                  |   31 --
 lib/ext_safe_renegotiation.c     |  383 ++++++++++++++-
 lib/ext_safe_renegotiation.h     |   26 +-
 lib/ext_server_name.c            |  221 +++++++--
 lib/ext_server_name.h            |   26 +-
 lib/ext_session_ticket.c         |  295 +++++++++---
 lib/ext_session_ticket.h         |   14 +-
 lib/ext_signature.c              |  173 ++++++-
 lib/ext_signature.h              |   14 +-
 lib/ext_srp.c                    |  126 +++++-
 lib/ext_srp.h                    |   20 +-
 lib/gnutls_buffers.c             |   18 +-
 lib/gnutls_constate.c            |   15 +-
 lib/gnutls_extensions.c          |  430 ++++++++++++++---
 lib/gnutls_extensions.h          |   56 +++
 lib/gnutls_handshake.c           |  222 ++-------
 lib/gnutls_int.h                 |  148 ++----
 lib/gnutls_kx.c                  |   62 +---
 lib/gnutls_mbuffers.c            |    2 +-
 lib/gnutls_mbuffers.h            |    2 +-
 lib/gnutls_record.c              |   65 +---
 lib/gnutls_session_pack.c        |  986 +++++++++++---------------------------
 lib/gnutls_state.c               |   17 +-
 lib/gnutls_str.c                 |  176 ++++++--
 lib/gnutls_str.h                 |  109 ++++-
 lib/gnutls_supplemental.c        |    8 +-
 lib/gnutls_supplemental.h        |    2 +-
 lib/includes/gnutls/compat.h     |    6 +
 lib/includes/gnutls/gnutls.h.in  |    5 -
 lib/libgnutls.map                |    7 +
 lib/openpgp/output.c             |   32 +-
 lib/pakchois/pakchois.c          |   32 ++
 lib/pkcs11.c                     |   52 +-
 lib/x509/dn.c                    |   10 +-
 lib/x509/output.c                |   76 ++--
 libextra/ext_inner_application.c |  153 +++++-
 libextra/ext_inner_application.h |   42 ++-
 libextra/gnutls_extra.c          |    6 +-
 libextra/gnutls_ia.c             |  108 ++++-
 src/cli.c                        |    9 +-
 src/serv.c                       |   28 --
 tests/Makefile.am                |    4 -
 tests/oprfi.c                    |  413 ----------------
 tests/tlsia.c                    |   14 +
 52 files changed, 2748 insertions(+), 2429 deletions(-)
 delete mode 100644 lib/ext_oprfi.c
 delete mode 100644 lib/ext_oprfi.h
 delete mode 100644 tests/oprfi.c

diff --git a/NEWS b/NEWS
index 3d947da..5213f18 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,10 @@ See the end for copying conditions.
 
 * Version 2.11.0 (unreleased)
 
+** libgnutls: Internal API for extensions augmented to allow
+safe storing and loading of data on resumption. OPRFI extension
+was removed.
+
 ** libgnutls: Added support for DSA-SHA256 and DSA-SHA224
 
 ** libgnutls: Added PKCS #11 support and an API to access objects in
diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi
index 13651a4..a29a092 100644
--- a/doc/cha-gtls-app.texi
+++ b/doc/cha-gtls-app.texi
@@ -10,7 +10,6 @@
 * Server examples::
 * Miscellaneous examples::
 * Compatibility with the OpenSSL library::
-* Opaque PRF Input TLS Extension::
 * Keying Material Exporters::
 @end menu
 
@@ -454,20 +453,6 @@ Current limitations imposed by the compatibility layer 
include:
 
 @end itemize
 
address@hidden Opaque PRF Input TLS Extension
address@hidden Opaque PRF Input TLS Extension
address@hidden Opaque PRF Input
-
-GnuTLS supports the Opaque PRF Input TLS extension
-(@code{draft-rescorla-tls-opaque-prf-input-00.txt}).  The API consists
-of one API for use in the client, @ref{gnutls_oprfi_enable_client},
-and one API for use in the server, @ref{gnutls_oprfi_enable_server}.
-You must invoke both functions before calling @ref{gnutls_handshake}.
-The server utilizes a callback function into the application.  The
-callback can look at the random string provided by the client, and
-also set the server string.  The string lengths must be equal
-according to the protocol.
-
 @node Keying Material Exporters
 @section Keying Material Exporters
 @cindex Keying Material Exporters
diff --git a/lib/auth_srp.c b/lib/auth_srp.c
index 8ab237c..43e463b 100644
--- a/lib/auth_srp.c
+++ b/lib/auth_srp.c
@@ -36,6 +36,7 @@
 #include "auth_srp.h"
 #include <gnutls_str.h>
 #include <gnutls_datum.h>
+#include <ext_srp.h>
 
 const mod_auth_st srp_auth_struct = {
   "SRP",
@@ -142,6 +143,16 @@ _gnutls_gen_srp_server_kx (gnutls_session_t session, 
opaque ** data)
   size_t n_b, tmp_size;
   char buf[64];
   uint8_t *data_b;
+  extension_priv_data_t epriv;
+  srp_ext_st * priv;
+
+  ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SRP, &epriv);
+  if (ret < 0) /* peer didn't send a username */
+    {
+      gnutls_assert();
+      return GNUTLS_E_UNKNOWN_SRP_USERNAME;
+    }
+  priv = epriv.ptr;
 
   if ((ret =
        _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
@@ -154,8 +165,7 @@ _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque 
** data)
   info = _gnutls_get_auth_info (session);
   username = info->username;
 
-  _gnutls_str_cpy (username, MAX_SRP_USERNAME,
-                  session->security_parameters.extensions.srp_username);
+  _gnutls_str_cpy (username, MAX_SRP_USERNAME, priv->username);
 
   ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);
 
@@ -264,7 +274,16 @@ _gnutls_gen_srp_client_kx (gnutls_session_t session, 
opaque ** data)
   char *username, *password;
   char buf[64];
   gnutls_srp_client_credentials_t cred;
+  extension_priv_data_t epriv;
+  srp_ext_st * priv;
 
+  ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SRP, &epriv);
+  if (ret < 0) /* peer didn't send a username */
+    {
+      gnutls_assert();
+      return GNUTLS_E_UNKNOWN_SRP_USERNAME;
+    }
+  priv = epriv.ptr;
 
   cred = (gnutls_srp_client_credentials_t)
     _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
@@ -275,15 +294,16 @@ _gnutls_gen_srp_client_kx (gnutls_session_t session, 
opaque ** data)
       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
     }
 
-  if (session->internals.srp_username == NULL)
+  if (priv->username == NULL)
     {
       username = cred->username;
       password = cred->password;
     }
   else
     {
-      username = session->internals.srp_username;
-      password = session->internals.srp_password;
+
+      username = priv->username;
+      password = priv->password;
     }
 
   if (username == NULL || password == NULL)
@@ -716,6 +736,16 @@ _gnutls_proc_srp_server_kx (gnutls_session_t session, 
opaque * data,
   char *username, *password;
   ssize_t data_size = _data_size;
   gnutls_srp_client_credentials_t cred;
+  extension_priv_data_t epriv;
+  srp_ext_st * priv;
+
+  ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SRP, &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return GNUTLS_E_UNKNOWN_SRP_USERNAME;
+    }
+  priv = epriv.ptr;
 
   cred = (gnutls_srp_client_credentials_t)
     _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);
@@ -726,15 +756,15 @@ _gnutls_proc_srp_server_kx (gnutls_session_t session, 
opaque * data,
       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
     }
 
-  if (session->internals.srp_username == NULL)
+  if (priv->username == NULL)
     {
       username = cred->username;
       password = cred->password;
     }
   else
     {
-      username = session->internals.srp_username;
-      password = session->internals.srp_password;
+      username = priv->username;
+      password = priv->password;
     }
 
   if (username == NULL || password == NULL)
diff --git a/lib/ext_cert_type.c b/lib/ext_cert_type.c
index 1351092..ea98511 100644
--- a/lib/ext_cert_type.c
+++ b/lib/ext_cert_type.c
@@ -34,8 +34,27 @@
 #include <gnutls_state.h>
 #include <gnutls_num.h>
 
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
 inline static int _gnutls_num2cert_type (int num);
 inline static int _gnutls_cert_type2num (int record_size);
+static int _gnutls_cert_type_recv_params (gnutls_session_t session,
+                                  const opaque * data, size_t data_size);
+static int _gnutls_cert_type_send_params (gnutls_session_t session, opaque * 
data,
+                                  size_t);
+
+extension_entry_st ext_mod_cert_type = {
+    .name = "CERT TYPE",
+    .type = GNUTLS_EXTENSION_CERT_TYPE,
+    .parse_type = GNUTLS_EXT_TLS,
+
+    .recv_func = _gnutls_cert_type_recv_params,
+    .send_func = _gnutls_cert_type_send_params,
+    .pack_func = NULL,
+    .unpack_func = NULL,
+    .deinit_func = NULL
+};
 
 /* 
  * In case of a server: if a CERT_TYPE extension type is received then it 
stores
@@ -46,7 +65,7 @@ inline static int _gnutls_cert_type2num (int record_size);
  *
  */
 
-int
+static int
 _gnutls_cert_type_recv_params (gnutls_session_t session,
                               const opaque * data, size_t _data_size)
 {
@@ -142,7 +161,7 @@ _gnutls_cert_type_recv_params (gnutls_session_t session,
 
 /* returns data_size or a negative number on failure
  */
-int
+static int
 _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data,
                               size_t data_size)
 {
diff --git a/lib/ext_cert_type.h b/lib/ext_cert_type.h
index 3ab9f2a..dc3b421 100644
--- a/lib/ext_cert_type.h
+++ b/lib/ext_cert_type.h
@@ -23,10 +23,11 @@
  *
  */
 
-/* Maps record size to numbers according to the
- * extensions draft.
- */
-int _gnutls_cert_type_recv_params (gnutls_session_t session,
-                                  const opaque * data, size_t data_size);
-int _gnutls_cert_type_send_params (gnutls_session_t session, opaque * data,
-                                  size_t);
+#ifndef EXT_CERT_TYPE_H
+#define EXT_CERT_TYPE_H
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_cert_type;
+
+#endif
diff --git a/lib/ext_max_record.c b/lib/ext_max_record.c
index 32bc918..9832668 100644
--- a/lib/ext_max_record.c
+++ b/lib/ext_max_record.c
@@ -28,8 +28,36 @@
 #include "gnutls_int.h"
 #include "gnutls_errors.h"
 #include "gnutls_num.h"
+#include <gnutls_extensions.h>
 #include <ext_max_record.h>
 
+static int _gnutls_max_record_recv_params (gnutls_session_t session,
+                                   const opaque * data, size_t data_size);
+static int _gnutls_max_record_send_params (gnutls_session_t session, opaque * 
data,
+                                   size_t);
+
+static int _gnutls_max_record_unpack(gnutls_buffer_st* ps, 
extension_priv_data_t* _priv);
+static int _gnutls_max_record_pack(extension_priv_data_t _priv, 
gnutls_buffer_st* ps);
+
+/* Maps record size to numbers according to the
+ * extensions draft.
+ */
+static int _gnutls_mre_num2record (int num);
+static int _gnutls_mre_record2num (uint16_t record_size);
+
+
+extension_entry_st ext_mod_max_record_size = {
+    .name = "MAX RECORD SIZE",
+    .type = GNUTLS_EXTENSION_MAX_RECORD_SIZE,
+    .parse_type = GNUTLS_EXT_TLS,
+
+    .recv_func = _gnutls_max_record_recv_params,
+    .send_func = _gnutls_max_record_send_params,
+    .pack_func = _gnutls_max_record_pack,
+    .unpack_func = _gnutls_max_record_unpack,
+    .deinit_func = NULL
+};
+
 /* 
  * In case of a server: if a MAX_RECORD_SIZE extension type is received then 
it stores
  * into the session the new value. The server may use 
gnutls_get_max_record_size(),
@@ -40,12 +68,14 @@
  *
  */
 
-int
+static int
 _gnutls_max_record_recv_params (gnutls_session_t session,
                                const opaque * data, size_t _data_size)
 {
   ssize_t new_size;
   ssize_t data_size = _data_size;
+  extension_priv_data_t epriv;
+  int ret;
 
   if (session->security_parameters.entity == GNUTLS_SERVER)
     {
@@ -66,10 +96,17 @@ _gnutls_max_record_recv_params (gnutls_session_t session,
        }
     }
   else
-    {                          /* CLIENT SIDE - we must check if the sent 
record size is the right one 
-                                */
+    {  /* CLIENT SIDE - we must check if the sent record size is the right one 
+        */
       if (data_size > 0)
        {
+         ret = _gnutls_ext_get_session_data( session, 
+           GNUTLS_EXTENSION_MAX_RECORD_SIZE, &epriv);
+         if (ret < 0)
+           {
+               gnutls_assert();
+               return GNUTLS_E_INTERNAL_ERROR;
+           }
 
          if (data_size != 1)
            {
@@ -79,8 +116,7 @@ _gnutls_max_record_recv_params (gnutls_session_t session,
 
          new_size = _gnutls_mre_num2record (data[0]);
 
-         if (new_size < 0
-             || new_size != session->internals.proposed_record_size)
+         if (new_size < 0 || new_size != epriv.num)
            {
              gnutls_assert ();
              return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
@@ -88,7 +124,7 @@ _gnutls_max_record_recv_params (gnutls_session_t session,
          else
            {
              session->security_parameters.max_record_recv_size =
-               session->internals.proposed_record_size;
+               epriv.num;
            }
 
        }
@@ -101,16 +137,26 @@ _gnutls_max_record_recv_params (gnutls_session_t session,
 
 /* returns data_size or a negative number on failure
  */
-int
+static int
 _gnutls_max_record_send_params (gnutls_session_t session, opaque * data,
                                size_t data_size)
 {
   uint16_t len;
+  int ret;
+   
   /* this function sends the client extension data (dnsname) */
   if (session->security_parameters.entity == GNUTLS_CLIENT)
     {
+      extension_priv_data_t epriv;
+      
+      ret = _gnutls_ext_get_session_data( session, 
+       GNUTLS_EXTENSION_MAX_RECORD_SIZE, &epriv);
+      if (ret < 0) /* it is ok not to have it */
+        {
+         return 0;
+       }
 
-      if (session->internals.proposed_record_size != DEFAULT_MAX_RECORD_SIZE)
+      if (epriv.num != DEFAULT_MAX_RECORD_SIZE)
        {
          len = 1;
          if (data_size < len)
@@ -120,8 +166,7 @@ _gnutls_max_record_send_params (gnutls_session_t session, 
opaque * data,
            }
 
          data[0] =
-           (uint8_t) _gnutls_mre_record2num (session->
-                                             internals.proposed_record_size);
+           (uint8_t) _gnutls_mre_record2num (epriv.num);
          return len;
        }
 
@@ -152,10 +197,36 @@ _gnutls_max_record_send_params (gnutls_session_t session, 
opaque * data,
   return 0;
 }
 
+
+static int _gnutls_max_record_pack(extension_priv_data_t epriv, 
gnutls_buffer_st* ps)
+{
+int ret;
+
+  BUFFER_APPEND_NUM(ps, epriv.num);
+
+  return 0;
+   
+}
+
+static int _gnutls_max_record_unpack(gnutls_buffer_st* ps, 
extension_priv_data_t* _priv)
+{
+extension_priv_data_t epriv;
+int ret;
+
+  BUFFER_POP_NUM(ps, epriv.num);
+  
+  *_priv = epriv;
+  
+  ret = 0;  
+error:
+  return ret;
+}
+
+
 /* Maps numbers to record sizes according to the
  * extensions draft.
  */
-int
+static int
 _gnutls_mre_num2record (int num)
 {
   switch (num)
@@ -176,7 +247,7 @@ _gnutls_mre_num2record (int num)
 /* Maps record size to numbers according to the
  * extensions draft.
  */
-int
+static int
 _gnutls_mre_record2num (uint16_t record_size)
 {
   switch (record_size)
@@ -194,3 +265,67 @@ _gnutls_mre_record2num (uint16_t record_size)
     }
 
 }
+
+/**
+ * gnutls_record_get_max_size:
+ * @session: is a #gnutls_session_t structure.
+ *
+ * Get the record size.  The maximum record size is negotiated by the
+ * client after the first handshake message.
+ *
+ * Returns: The maximum record packet size in this connection.
+ **/
+size_t
+gnutls_record_get_max_size (gnutls_session_t session)
+{
+  /* Recv will hold the negotiated max record size
+   * always.
+   */
+  return session->security_parameters.max_record_recv_size;
+}
+
+
+/**
+ * gnutls_record_set_max_size:
+ * @session: is a #gnutls_session_t structure.
+ * @size: is the new size
+ *
+ * This function sets the maximum record packet size in this
+ * connection.  This property can only be set to clients.  The server
+ * may choose not to accept the requested size.
+ *
+ * Acceptable values are 512(=2^9), 1024(=2^10), 2048(=2^11) and
+ * 4096(=2^12).  The requested record size does get in effect
+ * immediately only while sending data. The receive part will take
+ * effect after a successful handshake.
+ *
+ * This function uses a TLS extension called 'max record size'.  Not
+ * all TLS implementations use or even understand this extension.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
+ *   otherwise an error code is returned.
+ **/
+ssize_t
+gnutls_record_set_max_size (gnutls_session_t session, size_t size)
+{
+  ssize_t new_size;
+  extension_priv_data_t epriv;
+
+  if (session->security_parameters.entity == GNUTLS_SERVER)
+    return GNUTLS_E_INVALID_REQUEST;
+
+  new_size = _gnutls_mre_record2num (size);
+
+  if (new_size < 0)
+    {
+      gnutls_assert ();
+      return new_size;
+    }
+
+  session->security_parameters.max_record_send_size = size;
+  epriv.num = size;
+
+  _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_MAX_RECORD_SIZE, 
epriv);
+
+  return 0;
+}
diff --git a/lib/ext_max_record.h b/lib/ext_max_record.h
index bfc465f..d159b27 100644
--- a/lib/ext_max_record.h
+++ b/lib/ext_max_record.h
@@ -23,12 +23,11 @@
  *
  */
 
-/* Maps record size to numbers according to the
- * extensions draft.
- */
-int _gnutls_mre_num2record (int num);
-int _gnutls_mre_record2num (uint16_t record_size);
-int _gnutls_max_record_recv_params (gnutls_session_t session,
-                                   const opaque * data, size_t data_size);
-int _gnutls_max_record_send_params (gnutls_session_t session, opaque * data,
-                                   size_t);
+#ifndef EXT_MAX_RECORD_H
+#define EXT_MAX_RECORD_H
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_max_record_size;
+
+#endif
diff --git a/lib/ext_oprfi.c b/lib/ext_oprfi.c
deleted file mode 100644
index 1fad660..0000000
--- a/lib/ext_oprfi.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2007, 2010 Free Software Foundation, Inc.
- *
- * Author: Simon Josefsson
- *
- * This file is part of GnuTLS.
- *
- * The GnuTLS 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA
- *
- */
-
-/* Implementation of Opaque PRF Input:
- * http://tools.ietf.org/id/draft-rescorla-tls-opaque-prf-input-00.txt
- *
- */
-
-#include <ext_oprfi.h>
-
-#include <gnutls_errors.h>
-#include <gnutls_num.h>
-
-int
-oprfi_recv_server (gnutls_session_t session,
-                  const opaque * data, size_t _data_size)
-{
-  ssize_t data_size = _data_size;
-  uint16_t len;
-  int ret;
-
-  if (!session->internals.oprfi_cb)
-    {
-      gnutls_assert ();
-      return 0;
-    }
-
-  DECR_LEN (data_size, 2);
-  len = _gnutls_read_uint16 (data);
-  data += 2;
-
-  if (len != data_size)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
-    }
-
-  /* Store incoming data. */
-  session->security_parameters.extensions.oprfi_client_len = len;
-  session->security_parameters.extensions.oprfi_client = gnutls_malloc (len);
-  if (!session->security_parameters.extensions.oprfi_client)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-  memcpy (session->security_parameters.extensions.oprfi_client, data, len);
-
-  return 0;
-}
-
-int
-oprfi_recv_client (gnutls_session_t session,
-                  const opaque * data, size_t _data_size)
-{
-  ssize_t data_size = _data_size;
-  uint16_t len;
-  int ret;
-
-  if (session->security_parameters.extensions.oprfi_client == NULL)
-    {
-      gnutls_assert ();
-      return 0;
-    }
-
-  DECR_LEN (data_size, 2);
-  len = _gnutls_read_uint16 (data);
-  data += 2;
-
-  if (len != data_size)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
-    }
-
-  if (len != session->security_parameters.extensions.oprfi_client_len)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
-    }
-
-  /* Store incoming data. */
-  session->security_parameters.extensions.oprfi_server_len = len;
-  session->security_parameters.extensions.oprfi_server = gnutls_malloc (len);
-  if (!session->security_parameters.extensions.oprfi_server)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-  memcpy (session->security_parameters.extensions.oprfi_server, data, len);
-
-  return 0;
-}
-
-int
-_gnutls_oprfi_recv_params (gnutls_session_t session,
-                          const opaque * data, size_t data_size)
-{
-  if (session->security_parameters.entity == GNUTLS_CLIENT)
-    return oprfi_recv_client (session, data, data_size);
-  else
-    return oprfi_recv_server (session, data, data_size);
-}
-
-int
-oprfi_send_client (gnutls_session_t session, opaque * data, size_t _data_size)
-{
-  opaque *p = data;
-  ssize_t data_size = _data_size;
-  int oprf_size = session->security_parameters.extensions.oprfi_client_len;
-
-  if (oprf_size == 0)
-    return 0;
-
-  DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
-  _gnutls_write_uint16 (oprf_size, p);
-  p += 2;
-
-  DECR_LENGTH_RET (data_size, oprf_size, GNUTLS_E_SHORT_MEMORY_BUFFER);
-
-  memcpy (p, session->security_parameters.extensions.oprfi_client, oprf_size);
-
-  return 2 + oprf_size;
-}
-
-int
-oprfi_send_server (gnutls_session_t session, opaque * data, size_t _data_size)
-{
-  opaque *p = data;
-  int ret;
-  ssize_t data_size = _data_size;
-  size_t len;
-
-  if (!session->security_parameters.extensions.oprfi_client ||
-      !session->internals.oprfi_cb)
-    return 0;
-
-  /* Allocate buffer for outgoing data. */
-  session->security_parameters.extensions.oprfi_server_len =
-    session->security_parameters.extensions.oprfi_client_len;
-  session->security_parameters.extensions.oprfi_server =
-    gnutls_malloc (session->security_parameters.extensions.oprfi_server_len);
-  if (!session->security_parameters.extensions.oprfi_server)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  /* Get outgoing data. */
-  ret = session->internals.oprfi_cb
-    (session, session->internals.oprfi_userdata,
-     session->security_parameters.extensions.oprfi_client_len,
-     session->security_parameters.extensions.oprfi_client,
-     session->security_parameters.extensions.oprfi_server);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      gnutls_free (session->security_parameters.extensions.oprfi_server);
-      return ret;
-    }
-
-  DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
-  _gnutls_write_uint16 (session->security_parameters.extensions.
-                       oprfi_server_len, p);
-  p += 2;
-
-  DECR_LENGTH_RET (data_size,
-                  session->security_parameters.extensions.oprfi_server_len,
-                  GNUTLS_E_SHORT_MEMORY_BUFFER);
-
-  memcpy (p, session->security_parameters.extensions.oprfi_server,
-         session->security_parameters.extensions.oprfi_server_len);
-
-  return 2 + session->security_parameters.extensions.oprfi_server_len;
-}
-
-int
-_gnutls_oprfi_send_params (gnutls_session_t session,
-                          opaque * data, size_t data_size)
-{
-  if (session->security_parameters.entity == GNUTLS_CLIENT)
-    return oprfi_send_client (session, data, data_size);
-  else
-    return oprfi_send_server (session, data, data_size);
-}
-
-/**
- * gnutls_oprfi_enable_client:
- * @session: is a #gnutls_session_t structure.
- * @len: length of Opaque PRF data to use in client.
- * @data: Opaque PRF data to use in client.
- *
- * Request that the client should attempt to negotiate the Opaque PRF
- * Input TLS extension, using the given data as the client's Opaque
- * PRF input.
- *
- * The data is copied into the session context after this call, so you
- * may de-allocate it immediately after calling this function.
- **/
-void
-gnutls_oprfi_enable_client (gnutls_session_t session,
-                           size_t len, unsigned char *data)
-{
-  session->security_parameters.extensions.oprfi_client_len = len;
-  session->security_parameters.extensions.oprfi_client = data;
-}
-
-/**
- * gnutls_oprfi_enable_server:
- * @session: is a #gnutls_session_t structure.
- * @cb: function pointer to Opaque PRF extension server callback.
- * @userdata: hook passed to callback function for passing application state.
- *
- * Request that the server should attempt to accept the Opaque PRF
- * Input TLS extension.  If the client requests the extension, the
- * provided callback @cb will be invoked.  The callback must have the
- * following prototype:
- *
- * int callback (gnutls_session_t session, void *userdata,
- *               size_t oprfi_len, const unsigned char *in_oprfi,
- *               unsigned char *out_oprfi);
- *
- * The callback can inspect the client-provided data in the input
- * parameters, and specify its own opaque prf input data in the output
- * variable.  The function must return 0 on success, otherwise the
- * handshake will be aborted.
- **/
-void
-gnutls_oprfi_enable_server (gnutls_session_t session,
-                           gnutls_oprfi_callback_func cb, void *userdata)
-{
-  session->internals.oprfi_cb = cb;
-  session->internals.oprfi_userdata = userdata;
-}
diff --git a/lib/ext_oprfi.h b/lib/ext_oprfi.h
deleted file mode 100644
index 3df9d12..0000000
--- a/lib/ext_oprfi.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2007, 2010 Free Software Foundation, Inc.
- *
- * Author: Simon Josefsson
- *
- * This file is part of GnuTLS.
- *
- * The GnuTLS 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA
- *
- */
-
-#include <gnutls_int.h>
-
-int _gnutls_oprfi_recv_params (gnutls_session_t state,
-                              const opaque * data, size_t data_size);
-
-int _gnutls_oprfi_send_params (gnutls_session_t state,
-                              opaque * data, size_t data_size);
diff --git a/lib/ext_safe_renegotiation.c b/lib/ext_safe_renegotiation.c
index 14392b3..1e67f38 100644
--- a/lib/ext_safe_renegotiation.c
+++ b/lib/ext_safe_renegotiation.c
@@ -26,14 +26,229 @@
 #include <ext_safe_renegotiation.h>
 #include <gnutls_errors.h>
 
-int
-_gnutls_safe_renegotiation_recv_params (gnutls_session_t session,
+
+static int _gnutls_sr_recv_params (gnutls_session_t state,
+                                           const opaque * data,
+                                           size_t data_size);
+static int _gnutls_sr_send_params (gnutls_session_t state,
+                                           opaque * data, size_t);
+static int _gnutls_sr_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps);
+static int _gnutls_sr_unpack(gnutls_buffer_st* ps, extension_priv_data_t* 
_priv);
+static void _gnutls_sr_deinit_data(extension_priv_data_t priv);
+
+extension_entry_st ext_mod_sr = {
+    .name = "SAFE RENEGOTIATION",
+    .type = GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
+    .parse_type = GNUTLS_EXT_MANDATORY,
+
+    .recv_func = _gnutls_sr_recv_params,
+    .send_func = _gnutls_sr_send_params,
+    .pack_func = NULL,
+    .unpack_func = NULL,
+    .deinit_func = _gnutls_sr_deinit_data,
+};
+
+int _gnutls_ext_sr_finished( gnutls_session_t session, void* vdata, size_t 
vdata_size, int dir)
+{
+int ret;
+sr_ext_st* priv;
+extension_priv_data_t epriv;
+
+  if (session->internals.priorities.sr == SR_DISABLED)
+    {
+      return 0;
+    }
+
+  ret = _gnutls_ext_get_session_data( session, 
+    GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
+
+  /* Save data for safe renegotiation. 
+   */
+  if (vdata_size > MAX_VERIFY_DATA_SIZE)
+   {
+     gnutls_assert ();
+     return GNUTLS_E_INTERNAL_ERROR;
+   }
+
+  if ((session->security_parameters.entity == GNUTLS_CLIENT && dir == 0) ||
+    (session->security_parameters.entity == GNUTLS_SERVER && dir == 1))
+    {
+       priv->client_verify_data_len = vdata_size;
+       memcpy (priv->client_verify_data, vdata, vdata_size);
+    }
+  else
+    {
+       priv->server_verify_data_len = vdata_size;
+       memcpy (priv->server_verify_data, vdata, vdata_size);
+    }
+
+  return 0;
+}
+
+int _gnutls_ext_sr_verify(gnutls_session_t session)
+{
+int ret;
+sr_ext_st* priv = NULL;
+extension_priv_data_t epriv;
+
+  if (session->internals.priorities.sr == SR_DISABLED)
+    {
+      gnutls_assert ();
+      return 0;
+    }
+
+  ret = _gnutls_ext_get_session_data( session, 
+    GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+  if (ret >= 0)
+    priv = epriv.ptr;
+
+  /* Safe renegotiation */
+
+  if (priv && priv->safe_renegotiation_received)
+    {
+      if ((priv->ri_extension_data_len < priv->client_verify_data_len) ||
+         (memcmp (priv->ri_extension_data,
+                  priv->client_verify_data, priv->client_verify_data_len)))
+        {
+          gnutls_assert ();
+          _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
+                     session);
+          return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+        }
+
+      if (session->security_parameters.entity == GNUTLS_CLIENT)
+        {
+          if ((priv->ri_extension_data_len !=
+               priv->client_verify_data_len + priv->server_verify_data_len) ||
+              memcmp (priv->ri_extension_data + priv->client_verify_data_len,
+                  priv->server_verify_data,
+                  priv->server_verify_data_len) != 0)
+            {
+              gnutls_assert ();
+              _gnutls_handshake_log
+            ("HSK[%p]: Safe renegotiation failed [2]\n", session);
+              return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+            }
+        }
+      else                     /* Make sure there are 0 extra bytes */
+        {
+          if (priv->ri_extension_data_len != priv->client_verify_data_len)
+            {
+              gnutls_assert ();
+              _gnutls_handshake_log
+            ("HSK[%p]: Safe renegotiation failed [3]\n", session);
+              return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+            }
+        }
+
+      _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n",
+                            session);
+    }
+  else /* safe renegotiation not received... */
+    {
+      if (priv && priv->connection_using_safe_renegotiation)
+        {
+          gnutls_assert ();
+          _gnutls_handshake_log
+            ("HSK[%p]: Peer previously asked for safe renegotiation\n",
+             session);
+          return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+        }
+
+      /* Clients can't tell if it's an initial negotiation */
+      if (session->internals.initial_negotiation_completed)
+        {
+          if (session->internals.priorities.sr < SR_PARTIAL)
+            {
+              _gnutls_handshake_log
+            ("HSK[%p]: Allowing unsafe (re)negotiation\n", session);
+            }
+          else
+            {
+              gnutls_assert ();
+              _gnutls_handshake_log
+            ("HSK[%p]: Denying unsafe (re)negotiation\n", session);
+                  return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED;
+            }
+        }
+      else
+        {
+          if (session->internals.priorities.sr < SR_SAFE)
+            {
+              _gnutls_handshake_log
+            ("HSK[%p]: Allowing unsafe initial negotiation\n", session);
+            }
+          else
+            {
+              gnutls_assert ();
+              _gnutls_handshake_log
+            ("HSK[%p]: Denying unsafe initial negotiation\n", session);
+              return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
+            }
+        }
+    }
+    
+    return 0;
+}
+
+/* if a server received the special ciphersuite.
+ */
+int _gnutls_ext_sr_recv_cs(gnutls_session_t session)
+{
+  int ret, set = 0;
+  sr_ext_st* priv;
+  extension_priv_data_t epriv;
+
+  ret = _gnutls_ext_get_session_data( session, 
+    GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+  if (ret < 0)
+    {
+      set = 1;
+    }
+  else if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+
+  if (set != 0)
+    {
+      priv = gnutls_calloc(1, sizeof(*priv));
+      if (priv == NULL)
+        {
+             gnutls_assert();
+             return GNUTLS_E_MEMORY_ERROR;
+           }
+      epriv.ptr = priv;
+    }
+  else
+    priv = epriv.ptr;
+    
+  priv->safe_renegotiation_received = 1;
+  priv->connection_using_safe_renegotiation = 1;
+
+  if (set != 0)
+    _gnutls_ext_set_session_data( session, 
GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
+
+  return 0;    
+}
+
+static int
+_gnutls_sr_recv_params (gnutls_session_t session,
                                        const opaque * data,
                                        size_t _data_size)
 {
-  tls_ext_st *ext = &session->security_parameters.extensions;
   int len = data[0];
   ssize_t data_size = _data_size;
+  sr_ext_st* priv;
+  extension_priv_data_t epriv;
+  int set = 0, ret;
 
   DECR_LEN (data_size, len + 1 /* count the first byte and payload */ );
 
@@ -43,38 +258,65 @@ _gnutls_safe_renegotiation_recv_params (gnutls_session_t 
session,
       return 0;
     }
 
+  ret = _gnutls_ext_get_session_data( session, 
+    GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+  if (ret < 0 && session->security_parameters.entity == GNUTLS_SERVER)
+    {
+      set = 1;
+    }
+  else if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+
+  if (set != 0)
+    {
+      priv = gnutls_calloc(1, sizeof(*priv));
+      if (priv == NULL)
+        {
+             gnutls_assert();
+             return GNUTLS_E_MEMORY_ERROR;
+           }
+      epriv.ptr = priv;
+    }
+  else
+    priv = epriv.ptr;
+
   /* It is not legal to receive this extension on a renegotiation and
    * not receive it on the initial negotiation.
    */
   if (session->internals.initial_negotiation_completed != 0 &&
-      session->internals.connection_using_safe_renegotiation == 0)
+      priv->connection_using_safe_renegotiation == 0)
     {
       gnutls_assert ();
       return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
     }
 
-  if (len > sizeof (ext->ri_extension_data))
+  if (len > sizeof (priv->ri_extension_data))
     {
       gnutls_assert ();
       return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
     }
 
   if (len > 0)
-    memcpy (ext->ri_extension_data, &data[1], len);
-  ext->ri_extension_data_len = len;
+    memcpy (priv->ri_extension_data, &data[1], len);
+  priv->ri_extension_data_len = len;
 
   /* "safe renegotiation received" means on *this* handshake; "connection using
    * safe renegotiation" means that the initial hello received on the 
connection
    * indicated safe renegotiation.
    */
-  session->internals.safe_renegotiation_received = 1;
-  session->internals.connection_using_safe_renegotiation = 1;
+  priv->safe_renegotiation_received = 1;
+  priv->connection_using_safe_renegotiation = 1;
 
+  if (set != 0)
+    _gnutls_ext_set_session_data( session, 
GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
   return 0;
 }
 
-int
-_gnutls_safe_renegotiation_send_params (gnutls_session_t session,
+static int
+_gnutls_sr_send_params (gnutls_session_t session,
                                        opaque * data, size_t _data_size)
 {
   /* The format of this extension is a one-byte length of verify data followed
@@ -83,7 +325,9 @@ _gnutls_safe_renegotiation_send_params (gnutls_session_t 
session,
    * the minimum extension is one byte: 0x00.
    */
   ssize_t data_size = _data_size;
-  tls_ext_st *ext = &session->security_parameters.extensions;
+  sr_ext_st* priv;
+  int ret, set = 0;
+  extension_priv_data_t epriv;
 
   if (session->internals.priorities.sr == SR_DISABLED)
     {
@@ -91,31 +335,52 @@ _gnutls_safe_renegotiation_send_params (gnutls_session_t 
session,
       return 0;
     }
 
+  ret = _gnutls_ext_get_session_data( session, 
+    GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+  if (ret < 0)
+    {
+      set = 1;
+    }
+
+  if (set != 0)
+    {
+      priv = gnutls_calloc(1, sizeof(*priv));
+      if (priv == NULL)
+        {
+             gnutls_assert();
+             return GNUTLS_E_MEMORY_ERROR;
+           }
+      epriv.ptr = priv;
+     
+      _gnutls_ext_set_session_data( session, 
GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
+    }
+  else
+    priv = epriv.ptr;
+
   data[0] = 0;
 
   /* Always offer the extension if we're a client */
-  if (session->internals.connection_using_safe_renegotiation ||
+  if (priv->connection_using_safe_renegotiation ||
       session->security_parameters.entity == GNUTLS_CLIENT)
     {
       DECR_LEN (data_size, 1);
-      data[0] = ext->client_verify_data_len;
+      data[0] = priv->client_verify_data_len;
 
-      DECR_LEN (data_size, ext->client_verify_data_len);
+      DECR_LEN (data_size, priv->client_verify_data_len);
 
-      if (ext->client_verify_data_len > 0)
-       memcpy (&data[1], ext->client_verify_data,
-               ext->client_verify_data_len);
+      if (priv->client_verify_data_len > 0)
+        memcpy (&data[1], priv->client_verify_data, 
priv->client_verify_data_len);
 
       if (session->security_parameters.entity == GNUTLS_SERVER)
-       {
-         data[0] += ext->server_verify_data_len;
+           {
+             data[0] += priv->server_verify_data_len;
 
-         DECR_LEN (data_size, ext->server_verify_data_len);
+             DECR_LEN (data_size, priv->server_verify_data_len);
 
-         if (ext->server_verify_data_len > 0)
-           memcpy (&data[1 + ext->client_verify_data_len],
-                   ext->server_verify_data, ext->server_verify_data_len);
-       }
+          if (priv->server_verify_data_len > 0)
+            memcpy (&data[1 + priv->client_verify_data_len],
+                priv->server_verify_data, priv->server_verify_data_len);
+        }
     }
   else
     return 0;
@@ -123,6 +388,58 @@ _gnutls_safe_renegotiation_send_params (gnutls_session_t 
session,
   return 1 + data[0];          /* don't forget the length byte */
 }
 
+static void _gnutls_sr_deinit_data(extension_priv_data_t priv)
+{
+    gnutls_free(priv.ptr);
+}
+
+#if 0
+
+static int _gnutls_sr_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+sr_ext_st* priv = epriv.ptr;
+int ret;
+
+  BUFFER_APPEND_PFX(ps, priv->client_verify_data, 
priv->client_verify_data_len);
+  BUFFER_APPEND_PFX(ps, priv->server_verify_data, 
priv->server_verify_data_len);
+  BUFFER_APPEND_PFX(ps, priv->ri_extension_data, priv->ri_extension_data_len);
+  
+  return 0;
+}
+
+static int _gnutls_sr_unpack(gnutls_buffer_st* ps, extension_priv_data_t* 
_priv)
+{
+sr_ext_st* priv;
+int ret;
+extension_priv_data_t epriv;
+
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+      gnutls_assert();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  BUFFER_POP_NUM(ps, priv->client_verify_data_len);
+  BUFFER_POP(ps, priv->client_verify_data, priv->client_verify_data_len);
+
+  BUFFER_POP_NUM(ps, priv->server_verify_data_len);
+  BUFFER_POP(ps, priv->server_verify_data, priv->server_verify_data_len);
+
+  BUFFER_POP_NUM(ps, priv->ri_extension_data_len);
+  BUFFER_POP(ps, priv->ri_extension_data, priv->ri_extension_data_len);
+  
+  epriv.ptr = priv;
+  *_priv = epriv;
+  
+  ret = 0;
+
+error:
+  return ret;
+}
+
+#endif
+
 /**
  * gnutls_safe_renegotiation_status:
  * @session: is a #gnutls_session_t structure.
@@ -138,5 +455,19 @@ _gnutls_safe_renegotiation_send_params (gnutls_session_t 
session,
 int
 gnutls_safe_renegotiation_status (gnutls_session_t session)
 {
-  return session->internals.connection_using_safe_renegotiation;
+int ret;
+sr_ext_st* priv;
+extension_priv_data_t epriv;
+
+  ret = _gnutls_ext_get_session_data( session, 
+    GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return 0;
+    }
+  priv = epriv.ptr;
+
+  return priv->connection_using_safe_renegotiation;
 }
+
diff --git a/lib/ext_safe_renegotiation.h b/lib/ext_safe_renegotiation.h
index ca4fb7a..f79cca3 100644
--- a/lib/ext_safe_renegotiation.h
+++ b/lib/ext_safe_renegotiation.h
@@ -25,10 +25,26 @@
 #ifndef EXT_SAFE_RENEGOTIATION_H
 # define EXT_SAFE_RENEGOTIATION_H
 
-int _gnutls_safe_renegotiation_recv_params (gnutls_session_t state,
-                                           const opaque * data,
-                                           size_t data_size);
-int _gnutls_safe_renegotiation_send_params (gnutls_session_t state,
-                                           opaque * data, size_t);
+#include <gnutls_extensions.h>
+
+typedef struct {
+  uint8_t client_verify_data[MAX_VERIFY_DATA_SIZE];
+  size_t client_verify_data_len;
+  uint8_t server_verify_data[MAX_VERIFY_DATA_SIZE];
+  size_t server_verify_data_len;
+  uint8_t ri_extension_data[MAX_VERIFY_DATA_SIZE * 2];  /* max signal is 72 
bytes in s->c sslv3 */
+  size_t ri_extension_data_len;
+
+  int safe_renegotiation_received:1;
+  int initial_negotiation_completed:1;
+  int connection_using_safe_renegotiation:1;
+} sr_ext_st;
+
+extern extension_entry_st ext_mod_sr;
+
+int _gnutls_ext_sr_finished( gnutls_session_t session, void* vdata, 
+    size_t vdata_size, int dir);
+int _gnutls_ext_sr_recv_cs(gnutls_session_t session);
+int _gnutls_ext_sr_verify(gnutls_session_t session);
 
 #endif /* EXT_SAFE_RENEGOTIATION_H */
diff --git a/lib/ext_server_name.c b/lib/ext_server_name.c
index 85ff910..7b2face 100644
--- a/lib/ext_server_name.c
+++ b/lib/ext_server_name.c
@@ -29,6 +29,28 @@
 #include "gnutls_num.h"
 #include <ext_server_name.h>
 
+static int _gnutls_server_name_recv_params (gnutls_session_t session,
+                                    const opaque * data, size_t data_size);
+static int _gnutls_server_name_send_params (gnutls_session_t session,
+                                    opaque * data, size_t);
+
+static int _gnutls_server_name_unpack(gnutls_buffer_st* ps, 
extension_priv_data_t* _priv);
+static int _gnutls_server_name_pack(extension_priv_data_t _priv, 
gnutls_buffer_st* ps);
+static void _gnutls_server_name_deinit_data(extension_priv_data_t priv);
+
+
+extension_entry_st ext_mod_server_name = {
+    .name = "SERVER NAME",
+    .type = GNUTLS_EXTENSION_SERVER_NAME,
+    .parse_type = GNUTLS_EXT_APPLICATION,
+
+    .recv_func = _gnutls_server_name_recv_params,
+    .send_func = _gnutls_server_name_send_params,
+    .pack_func = _gnutls_server_name_pack,
+    .unpack_func = _gnutls_server_name_unpack,
+    .deinit_func = _gnutls_server_name_deinit_data,
+};
+
 /*
  * In case of a server: if a NAME_DNS extension type is received then
  * it stores into the session the value of NAME_DNS. The server may
@@ -38,9 +60,7 @@
  * in the session then it sends the extension to the peer.
  *
  */
-
-int
-_gnutls_server_name_recv_params (gnutls_session_t session,
+static int _gnutls_server_name_recv_params (gnutls_session_t session,
                                 const opaque * data, size_t _data_size)
 {
   int i;
@@ -48,7 +68,9 @@ _gnutls_server_name_recv_params (gnutls_session_t session,
   uint16_t len, type;
   ssize_t data_size = _data_size;
   int server_names = 0;
-
+  server_name_ext_st* priv;
+  extension_priv_data_t epriv;
+  
   if (session->security_parameters.entity == GNUTLS_SERVER)
     {
       DECR_LENGTH_RET (data_size, 2, 0);
@@ -98,11 +120,17 @@ _gnutls_server_name_recv_params (gnutls_session_t session,
          server_names = MAX_SERVER_NAME_EXTENSIONS;
        }
 
-      session->security_parameters.extensions.server_names_size =
-       server_names;
       if (server_names == 0)
        return 0;               /* no names found */
 
+      priv = gnutls_calloc(1, sizeof(*priv));
+      if (priv == NULL)
+        {
+           gnutls_assert();
+           return GNUTLS_E_MEMORY_ERROR;
+       }
+
+      priv->server_names_size = server_names;
 
       p = data + 2;
       for (i = 0; i < server_names; i++)
@@ -115,15 +143,12 @@ _gnutls_server_name_recv_params (gnutls_session_t session,
 
          switch (type)
            {
-           case 0:             /* NAME_DNS */
+           case 0: /* NAME_DNS */
              if (len <= MAX_SERVER_NAME_SIZE)
                {
-                 memcpy (session->security_parameters.
-                         extensions.server_names[i].name, p, len);
-                 session->security_parameters.extensions.server_names[i].
-                   name_length = len;
-                 session->security_parameters.extensions.server_names[i].
-                   type = GNUTLS_NAME_DNS;
+                 memcpy (priv->server_names[i].name, p, len);
+                 priv->server_names[i].name_length = len;
+                 priv->server_names[i].type = GNUTLS_NAME_DNS;
                  break;
                }
            }
@@ -131,13 +156,18 @@ _gnutls_server_name_recv_params (gnutls_session_t session,
          /* move to next record */
          p += len;
        }
+
+      epriv.ptr = priv;
+      _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, 
epriv);
+
     }
+
   return 0;
 }
 
 /* returns data_size or a negative number on failure
  */
-int
+static int
 _gnutls_server_name_send_params (gnutls_session_t session,
                                 opaque * data, size_t _data_size)
 {
@@ -145,27 +175,33 @@ _gnutls_server_name_send_params (gnutls_session_t session,
   opaque *p;
   unsigned i;
   ssize_t data_size = _data_size;
-  int total_size = 0;
+  int total_size = 0, ret;
+  server_name_ext_st* priv;
+  extension_priv_data_t epriv;
+
+  ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, 
&epriv);
+  if (ret < 0)
+    return 0;
+
 
   /* this function sends the client extension data (dnsname)
    */
   if (session->security_parameters.entity == GNUTLS_CLIENT)
     {
+      priv = epriv.ptr;
 
-      if (session->security_parameters.extensions.server_names_size == 0)
+      if (priv->server_names_size == 0)
        return 0;
 
       /* uint16_t
        */
       total_size = 2;
       for (i = 0;
-          i < session->security_parameters.extensions.server_names_size; i++)
+          i < priv->server_names_size; i++)
        {
          /* count the total size
           */
-         len =
-           session->security_parameters.extensions.
-           server_names[i].name_length;
+         len = priv->server_names[i].name_length;
 
          /* uint8_t + uint16_t + size
           */
@@ -179,19 +215,14 @@ _gnutls_server_name_send_params (gnutls_session_t session,
       DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
       _gnutls_write_uint16 (total_size - 2, p);
       p += 2;
-
       for (i = 0;
-          i < session->security_parameters.extensions.server_names_size; i++)
+          i < priv->server_names_size; i++)
        {
 
-         switch (session->security_parameters.extensions.server_names[i].
-                 type)
+         switch (priv->server_names[i].type)
            {
            case GNUTLS_NAME_DNS:
-
-             len =
-               session->security_parameters.extensions.server_names[i].
-               name_length;
+             len = priv->server_names[i].name_length;
              if (len == 0)
                break;
 
@@ -208,9 +239,7 @@ _gnutls_server_name_send_params (gnutls_session_t session,
              _gnutls_write_uint16 (len, p);
              p += 2;
 
-             memcpy (p,
-                     session->security_parameters.extensions.server_names[i].
-                     name, len);
+             memcpy (p, priv->server_names[i].name, len);
              p += len;
              break;
            default:
@@ -257,28 +286,37 @@ gnutls_server_name_get (gnutls_session_t session, void 
*data,
                        unsigned int *type, unsigned int indx)
 {
   char *_data = data;
+  server_name_ext_st* priv;
+  int ret;
+  extension_priv_data_t epriv;
 
   if (session->security_parameters.entity == GNUTLS_CLIENT)
     {
       gnutls_assert ();
       return GNUTLS_E_INVALID_REQUEST;
     }
+  
+  ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, 
&epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+    }
+ 
+  priv = epriv.ptr;
 
-  if (indx + 1 > session->security_parameters.extensions.server_names_size)
+  if (indx + 1 > priv->server_names_size)
     {
       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     }
 
-  *type = session->security_parameters.extensions.server_names[indx].type;
+  *type = priv->server_names[indx].type;
 
-  if (*data_length >           /* greater since we need one extra byte for the 
null */
-      session->security_parameters.extensions.server_names[indx].name_length)
+  if (*data_length > /* greater since we need one extra byte for the null */
+      priv->server_names[indx].name_length)
     {
-      *data_length =
-       session->security_parameters.extensions.
-       server_names[indx].name_length;
-      memcpy (data,
-             session->security_parameters.extensions.server_names[indx].name,
+      *data_length = priv->server_names[indx].name_length;
+      memcpy (data, priv->server_names[indx].name,
              *data_length);
 
       if (*type == GNUTLS_NAME_DNS)    /* null terminate */
@@ -287,9 +325,7 @@ gnutls_server_name_get (gnutls_session_t session, void 
*data,
     }
   else
     {
-      *data_length =
-       session->security_parameters.extensions.
-       server_names[indx].name_length;
+      *data_length = priv->server_names[indx].name_length;
       return GNUTLS_E_SHORT_MEMORY_BUFFER;
     }
 
@@ -321,7 +357,10 @@ gnutls_server_name_set (gnutls_session_t session,
                        gnutls_server_name_type_t type,
                        const void *name, size_t name_length)
 {
-  int server_names;
+  int server_names, ret;
+  server_name_ext_st* priv;
+  extension_priv_data_t epriv;
+  int set = 0;
 
   if (session->security_parameters.entity == GNUTLS_SERVER)
     {
@@ -332,21 +371,95 @@ gnutls_server_name_set (gnutls_session_t session,
   if (name_length > MAX_SERVER_NAME_SIZE)
     return GNUTLS_E_SHORT_MEMORY_BUFFER;
 
-  server_names =
-    session->security_parameters.extensions.server_names_size + 1;
+  ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, 
&epriv);
+  if (ret < 0)
+    {
+      set = 1;
+    }
+
+  if (set != 0)
+    {
+      priv = gnutls_calloc(1, sizeof(*priv));
+      if (priv == NULL)
+        {
+           gnutls_assert();
+           return GNUTLS_E_MEMORY_ERROR;
+       }
+      epriv.ptr = priv;
+    }
+  else
+    priv = epriv.ptr;
+  
+  server_names = priv->server_names_size + 1;
 
   if (server_names > MAX_SERVER_NAME_EXTENSIONS)
     server_names = MAX_SERVER_NAME_EXTENSIONS;
 
-  session->security_parameters.extensions.server_names
-    [server_names - 1].type = type;
-  memcpy (session->security_parameters.
-         extensions.server_names[server_names - 1].name, name, name_length);
-  session->security_parameters.extensions.server_names[server_names -
-                                                      1].name_length =
-    name_length;
+  priv->server_names[server_names - 1].type = type;
+  memcpy (priv->server_names[server_names - 1].name, name, name_length);
+  priv->server_names[server_names - 1].name_length = name_length;
+
+  priv->server_names_size++;
+  
+  if (set != 0)
+    _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SERVER_NAME, epriv);
+
+  return 0;
+}
+
+static void _gnutls_server_name_deinit_data(extension_priv_data_t priv)
+{
+    gnutls_free(priv.ptr);
+}
+
+static int _gnutls_server_name_pack(extension_priv_data_t epriv, 
gnutls_buffer_st* ps)
+{
+server_name_ext_st* priv = epriv.ptr;
+int i, ret;
+
+  BUFFER_APPEND_NUM(ps, priv->server_names_size);
+  for (i = 0; i < priv->server_names_size;i++)
+    {
+      BUFFER_APPEND_NUM(ps, priv->server_names[i].type);
+      BUFFER_APPEND_PFX(ps, priv->server_names[i].name, 
+       priv->server_names[i].name_length);
+    }
+  return 0;
+}
+
+static int _gnutls_server_name_unpack(gnutls_buffer_st* ps, 
extension_priv_data_t* _priv)
+{
+server_name_ext_st* priv;
+int i, ret;
+extension_priv_data_t epriv;
 
-  session->security_parameters.extensions.server_names_size++;
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+      gnutls_assert();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
 
+  BUFFER_POP_NUM(ps, priv->server_names_size);
+  for (i = 0; i < priv->server_names_size;i++)
+    {
+      BUFFER_POP_NUM(ps, priv->server_names[i].type);
+      BUFFER_POP_NUM(ps, priv->server_names[i].name_length);
+      if (priv->server_names[i].name_length > 
sizeof(priv->server_names[i].name))
+        {
+         gnutls_assert();
+         return GNUTLS_E_PARSING_ERROR;
+       }
+      BUFFER_POP(ps, priv->server_names[i].name, 
priv->server_names[i].name_length);
+    }
+
+  epriv.ptr = priv;
+  *_priv = epriv;
+  
   return 0;
+
+error:
+  gnutls_free(priv);
+  return ret;
 }
+
diff --git a/lib/ext_server_name.h b/lib/ext_server_name.h
index a598e1c..af36ce8 100644
--- a/lib/ext_server_name.h
+++ b/lib/ext_server_name.h
@@ -22,8 +22,26 @@
  * USA
  *
  */
+#ifndef EXT_SERVER_NAME_H
+#define EXT_SERVER_NAME_H
 
-int _gnutls_server_name_recv_params (gnutls_session_t session,
-                                    const opaque * data, size_t data_size);
-int _gnutls_server_name_send_params (gnutls_session_t session,
-                                    opaque * data, size_t);
+#include <gnutls_extensions.h>
+
+typedef struct
+{
+  opaque name[MAX_SERVER_NAME_SIZE];
+  unsigned name_length;
+  gnutls_server_name_type_t type;
+} server_name_st;
+
+#define MAX_SERVER_NAME_EXTENSIONS 3
+
+typedef struct {
+  server_name_st server_names[MAX_SERVER_NAME_EXTENSIONS];
+  /* limit server_name extensions */
+  unsigned server_names_size;
+} server_name_ext_st;
+
+extern extension_entry_st ext_mod_server_name;
+
+#endif
diff --git a/lib/ext_session_ticket.c b/lib/ext_session_ticket.c
index 2f000fe..fafb174 100644
--- a/lib/ext_session_ticket.c
+++ b/lib/ext_session_ticket.c
@@ -33,6 +33,7 @@
 #include <random.h>
 #include <ext_session_ticket.h>
 #include <gnutls_mbuffers.h>
+#include <gnutls_extensions.h>
 
 #ifdef ENABLE_SESSION_TICKET
 
@@ -43,6 +44,45 @@
 
 #define MAC_SIZE 32
 
+static int session_ticket_recv_params (gnutls_session_t session,
+                                       const opaque * data,
+                                       size_t data_size);
+static int session_ticket_send_params (gnutls_session_t session,
+                                       opaque * data, size_t data_size);
+static int session_ticket_unpack(gnutls_buffer_st* ps, extension_priv_data_t* 
_priv);
+static int session_ticket_pack(extension_priv_data_t _priv, gnutls_buffer_st* 
ps);
+static void session_ticket_deinit_data(extension_priv_data_t priv);
+
+extension_entry_st ext_mod_session_ticket = {
+    .name = "SESSION TICKET",
+    .type = GNUTLS_EXTENSION_SESSION_TICKET,
+    .parse_type = GNUTLS_EXT_TLS,
+
+    .recv_func = session_ticket_recv_params,
+    .send_func = session_ticket_send_params,
+    .pack_func = session_ticket_pack,
+    .unpack_func = session_ticket_unpack,
+    .deinit_func = session_ticket_deinit_data,
+};
+
+struct gnutls_session_ticket_key_st
+{
+  opaque key_name[SESSION_TICKET_KEY_NAME_SIZE];
+  opaque key[SESSION_TICKET_KEY_SIZE];
+  opaque mac_secret[SESSION_TICKET_MAC_SECRET_SIZE];
+};
+
+typedef struct {
+    int session_ticket_enable;
+    int session_ticket_renew;
+    opaque session_ticket_IV[SESSION_TICKET_IV_SIZE];
+
+    opaque* session_ticket;
+    int session_ticket_len;
+
+    struct gnutls_session_ticket_key_st key;
+} session_ticket_ext_st;
+
 struct ticket
 {
   opaque key_name[KEY_NAME_SIZE];
@@ -79,17 +119,16 @@ digest_ticket (const gnutls_datum_t * key, struct ticket 
*ticket,
 }
 
 static int
-decrypt_ticket (gnutls_session_t session, struct ticket *ticket)
+decrypt_ticket (gnutls_session_t session, session_ticket_ext_st* priv, struct 
ticket *ticket)
 {
   cipher_hd_st cipher_hd;
   gnutls_datum_t key, IV, mac_secret, state;
-  opaque final[32];
+  opaque final[MAC_SECRET_SIZE];
   time_t timestamp = time (0);
   int ret;
 
   /* Check the integrity of ticket using HMAC-SHA-256. */
-  mac_secret.data = (void *)
-    session->internals.session_ticket_key->mac_secret;
+  mac_secret.data = (void *) priv->key.mac_secret;
   mac_secret.size = MAC_SECRET_SIZE;
   ret = digest_ticket (&mac_secret, ticket, final);
   if (ret < 0)
@@ -105,7 +144,7 @@ decrypt_ticket (gnutls_session_t session, struct ticket 
*ticket)
     }
 
   /* Decrypt encrypted_state using 128-bit AES in CBC mode. */
-  key.data = (void *) session->internals.session_ticket_key->key;
+  key.data = (void *) priv->key.key;
   key.size = KEY_SIZE;
   IV.data = ticket->IV;
   IV.size = IV_SIZE;
@@ -149,7 +188,7 @@ decrypt_ticket (gnutls_session_t session, struct ticket 
*ticket)
 }
 
 static int
-encrypt_ticket (gnutls_session_t session, struct ticket *ticket)
+encrypt_ticket (gnutls_session_t session, session_ticket_ext_st* priv, struct 
ticket *ticket)
 {
   cipher_hd_st cipher_hd;
   gnutls_datum_t key, IV, mac_secret, state, encrypted_state;
@@ -164,6 +203,7 @@ encrypt_ticket (gnutls_session_t session, struct ticket 
*ticket)
       return ret;
     }
   blocksize = gnutls_cipher_get_block_size (GNUTLS_CIPHER_AES_128_CBC);
+
   encrypted_state.size =
     ((state.size + blocksize - 1) / blocksize) * blocksize;
   encrypted_state.data = gnutls_malloc (encrypted_state.size);
@@ -178,9 +218,9 @@ encrypt_ticket (gnutls_session_t session, struct ticket 
*ticket)
   _gnutls_free_datum (&state);
 
   /* Encrypt state using 128-bit AES in CBC mode. */
-  key.data = (void *) session->internals.session_ticket_key->key;
+  key.data = (void *) priv->key.key;
   key.size = KEY_SIZE;
-  IV.data = session->internals.session_ticket_IV;
+  IV.data = priv->session_ticket_IV;
   IV.size = IV_SIZE;
   ret =
     _gnutls_cipher_init (&cipher_hd, GNUTLS_CIPHER_AES_128_CBC, &key, &IV);
@@ -202,14 +242,12 @@ encrypt_ticket (gnutls_session_t session, struct ticket 
*ticket)
     }
 
   /* Fill the ticket structure to compute MAC. */
-  memcpy (ticket->key_name,
-         session->internals.session_ticket_key->key_name, KEY_NAME_SIZE);
+  memcpy (ticket->key_name, priv->key.key_name, KEY_NAME_SIZE);
   memcpy (ticket->IV, IV.data, IV.size);
   ticket->encrypted_state_len = encrypted_state.size;
   ticket->encrypted_state = encrypted_state.data;
 
-  mac_secret.data =
-    (void *) session->internals.session_ticket_key->mac_secret;
+  mac_secret.data = priv->key.mac_secret;
   mac_secret.size = MAC_SECRET_SIZE;
   ret = digest_ticket (&mac_secret, ticket, ticket->mac);
   if (ret < 0)
@@ -222,13 +260,24 @@ encrypt_ticket (gnutls_session_t session, struct ticket 
*ticket)
   return 0;
 }
 
-int
-_gnutls_session_ticket_recv_params (gnutls_session_t session,
+static int
+session_ticket_recv_params (gnutls_session_t session,
                                    const opaque * data, size_t _data_size)
 {
   ssize_t data_size = _data_size;
+  session_ticket_ext_st* priv=NULL;
+  extension_priv_data_t epriv;
+  int ret;
 
-  if (!session->internals.session_ticket_enable)
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
+
+  if (!priv->session_ticket_enable)
     return 0;
 
   if (session->security_parameters.entity == GNUTLS_SERVER)
@@ -240,7 +289,7 @@ _gnutls_session_ticket_recv_params (gnutls_session_t 
session,
       /* The client requested a new session ticket. */
       if (data_size == 0)
        {
-         session->internals.session_ticket_renew = 1;
+         priv->session_ticket_renew = 1;
          return 0;
        }
 
@@ -250,11 +299,9 @@ _gnutls_session_ticket_recv_params (gnutls_session_t 
session,
 
       /* If the key name of the ticket does not match the one that we
          hold, issue a new ticket. */
-      if (memcmp (ticket.key_name,
-                 session->internals.session_ticket_key->key_name,
-                 KEY_NAME_SIZE))
+      if (memcmp (ticket.key_name, priv->key.key_name, KEY_NAME_SIZE))
        {
-         session->internals.session_ticket_renew = 1;
+         priv->session_ticket_renew = 1;
          return 0;
        }
 
@@ -283,19 +330,19 @@ _gnutls_session_ticket_recv_params (gnutls_session_t 
session,
       memcpy (ticket.encrypted_state, encrypted_state,
              ticket.encrypted_state_len);
 
-      ret = decrypt_ticket (session, &ticket);
+      ret = decrypt_ticket (session, priv, &ticket);
       gnutls_free (ticket.encrypted_state);
       if (ret < 0)
        {
-         session->internals.session_ticket_renew = 1;
+         priv->session_ticket_renew = 1;
          return 0;
        }
     }
-  else
+  else /* Client */
     {
       if (data_size == 0)
        {
-         session->internals.session_ticket_renew = 1;
+         priv->session_ticket_renew = 1;
          return 0;
        }
     }
@@ -306,39 +353,44 @@ _gnutls_session_ticket_recv_params (gnutls_session_t 
session,
 /* returns a positive number if we send the extension data, zero if we
    do not want to send it, and a negative number on failure.
  */
-int
-_gnutls_session_ticket_send_params (gnutls_session_t session,
+static int
+session_ticket_send_params (gnutls_session_t session,
                                    opaque * data, size_t _data_size)
 {
   ssize_t data_size = _data_size;
+  session_ticket_ext_st* priv=NULL;
+  extension_priv_data_t epriv;
+  int ret;
 
-  if (!session->internals.session_ticket_enable)
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+  if (ret >= 0)
+    priv = epriv.ptr;
+
+  if (priv == NULL || !priv->session_ticket_enable)
     return 0;
 
   if (session->security_parameters.entity == GNUTLS_SERVER)
     {
-      if (session->internals.session_ticket_renew)
+      if (priv && priv->session_ticket_renew)
        {
          return GNUTLS_E_INT_RET_0;
        }
     }
   else
     {
-      if (session->internals.resumed_security_parameters.
-         extensions.session_ticket_len > 0)
+      ret = _gnutls_ext_get_resumed_session_data( session, 
GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+      if (ret >= 0)
+       priv = epriv.ptr;
+
+      if (ret < 0 || !priv->session_ticket_enable)
+       return 0;
+
+      if (priv->session_ticket_len > 0)
        {
-         DECR_LENGTH_RET (data_size,
-                          session->internals.
-                          resumed_security_parameters.extensions.
-                          session_ticket_len, GNUTLS_E_SHORT_MEMORY_BUFFER);
-         memcpy (data,
-                 session->internals.resumed_security_parameters.
-                 extensions.session_ticket,
-                 session->internals.resumed_security_parameters.
-                 extensions.session_ticket_len);
-
-         return session->internals.resumed_security_parameters.extensions.
-           session_ticket_len;
+         DECR_LENGTH_RET (data_size, priv->session_ticket_len, 
GNUTLS_E_SHORT_MEMORY_BUFFER);
+         memcpy (data, priv->session_ticket, priv->session_ticket_len);
+
+         return priv->session_ticket_len;
        }
       else
        {
@@ -348,6 +400,55 @@ _gnutls_session_ticket_send_params (gnutls_session_t 
session,
   return 0;
 }
 
+
+static void session_ticket_deinit_data(extension_priv_data_t epriv)
+{
+session_ticket_ext_st* priv = epriv.ptr;
+
+    gnutls_free(priv->session_ticket);
+    gnutls_free(priv);
+}
+
+static int session_ticket_pack(extension_priv_data_t epriv, gnutls_buffer_st* 
ps)
+{
+session_ticket_ext_st* priv = epriv.ptr;
+int ret;
+
+  BUFFER_APPEND_PFX(ps, priv->session_ticket, priv->session_ticket_len);
+
+  return 0;
+}
+
+static int session_ticket_unpack(gnutls_buffer_st* ps, extension_priv_data_t* 
_priv)
+{
+session_ticket_ext_st* priv=NULL;
+int ret;
+extension_priv_data_t epriv;
+gnutls_datum ticket;
+
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+      gnutls_assert();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+  
+  BUFFER_POP_DATUM(ps, &ticket);
+  priv->session_ticket = ticket.data;
+  priv->session_ticket_len = ticket.size;
+
+  epriv.ptr = priv;
+  *_priv = epriv;
+  
+  ret = 0;
+
+error:
+  gnutls_free(priv);
+  return ret;
+}
+
+
+
 /**
  * gnutls_session_ticket_key_generate:
  * @key: is a pointer to a #gnutls_datum_t which will contain a newly
@@ -400,13 +501,27 @@ gnutls_session_ticket_key_generate (gnutls_datum_t * key)
 int
 gnutls_session_ticket_enable_client (gnutls_session_t session)
 {
+  session_ticket_ext_st* priv=NULL;
+  extension_priv_data_t epriv;
+
   if (!session)
     {
       gnutls_assert ();
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  session->internals.session_ticket_enable = 1;
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+       gnutls_assert();
+       return GNUTLS_E_MEMORY_ERROR;
+    }
+  priv->session_ticket_enable = 1;
+  epriv.ptr = priv;
+
+  _gnutls_ext_set_session_data(session, 
+    GNUTLS_EXTENSION_SESSION_TICKET, epriv);
+  
   return 0;
 }
 
@@ -429,6 +544,8 @@ gnutls_session_ticket_enable_server (gnutls_session_t 
session,
                                     const gnutls_datum_t * key)
 {
   int ret;
+  session_ticket_ext_st* priv=NULL;
+  extension_priv_data_t epriv;
 
   if (!session || !key
       || key->size != sizeof (struct gnutls_session_ticket_key_st))
@@ -437,33 +554,31 @@ gnutls_session_ticket_enable_server (gnutls_session_t 
session,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+       gnutls_assert();
+       return GNUTLS_E_MEMORY_ERROR;
+    }
+  epriv.ptr = priv;
+
   ret = _gnutls_rnd (GNUTLS_RND_RANDOM,
-                    session->internals.session_ticket_IV, IV_SIZE);
+                    priv->session_ticket_IV, IV_SIZE);
   if (ret < 0)
     {
       gnutls_assert ();
       return ret;
     }
 
-  session->internals.session_ticket_key =
-    (struct gnutls_session_ticket_key_st *) key->data;
-  session->internals.session_ticket_enable = 1;
+  memcpy(&priv->key, key->data, key->size);
+  priv->session_ticket_enable = 1;
+
+  _gnutls_ext_set_session_data(session, 
+    GNUTLS_EXTENSION_SESSION_TICKET, epriv);
+
   return 0;
 }
 
-int
-_gnutls_send_new_session_ticket (gnutls_session_t session, int again)
-{
-  mbuffer_st *bufel = NULL;
-  uint8_t *data = NULL, *p;
-  int data_size = 0;
-  int ret;
-  struct ticket ticket;
-  uint16_t ticket_len;
-  gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
-  gnutls_mac_algorithm_t write_mac_algorithm;
-  gnutls_compression_method_t write_compression_algorithm;
-
 #define SAVE_WRITE_SECURITY_PARAMETERS                                 \
   do                                                                   \
     {                                                                  \
@@ -488,8 +603,31 @@ _gnutls_send_new_session_ticket (gnutls_session_t session, 
int again)
     }                                                                  \
   while (0)
 
+int
+_gnutls_send_new_session_ticket (gnutls_session_t session, int again)
+{
+  mbuffer_st *bufel = NULL;
+  uint8_t *data = NULL, *p;
+  int data_size = 0;
+  int ret;
+  struct ticket ticket;
+  uint16_t ticket_len;
+  gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
+  gnutls_mac_algorithm_t write_mac_algorithm;
+  gnutls_compression_method_t write_compression_algorithm;
+  session_ticket_ext_st* priv=NULL;
+  extension_priv_data_t epriv;
+
   if (again == 0)
     {
+      ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+      if (ret < 0)
+        return 0;
+      priv = epriv.ptr;
+      
+      if (!priv->session_ticket_renew)
+       return 0;
+      
       /* XXX: Temporarily set write algorithms to be used.
          _gnutls_write_connection_state_init() does this job, but it also
          triggers encryption, while NewSessionTicket should not be
@@ -514,7 +652,7 @@ _gnutls_send_new_session_ticket (gnutls_session_t session, 
int again)
       if (ret < 0)
        return ret;
 
-      ret = encrypt_ticket (session, &ticket);
+      ret = encrypt_ticket (session, priv, &ticket);
       RESTORE_WRITE_SECURITY_PARAMETERS;
       if (ret < 0)
        {
@@ -535,9 +673,8 @@ _gnutls_send_new_session_ticket (gnutls_session_t session, 
int again)
 
       data = _mbuffer_get_udata_ptr(bufel);
       p = data;
-      /* FIXME: ticket lifetime is fixed to 10 days, which should be
-         customizable. */
-      _gnutls_write_uint32 (864000, p);
+
+      _gnutls_write_uint32 ( session->internals.expire_time, p);
       p += 4;
 
       _gnutls_write_uint16 (ticket_len, p);
@@ -576,6 +713,19 @@ _gnutls_recv_new_session_ticket (gnutls_session_t session)
   uint32_t lifetime_hint;
   uint16_t ticket_len;
   int ret;
+  session_ticket_ext_st* priv=NULL;
+  extension_priv_data_t epriv;
+
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_SESSION_TICKET, &epriv);
+  if (ret < 0)
+    {
+       gnutls_assert();
+       return 0;
+    }
+  priv = epriv.ptr;
+
+  if (!priv->session_ticket_renew)
+    return 0;
 
   ret = _gnutls_recv_handshake (session, &data, &data_size,
                                GNUTLS_HANDSHAKE_NEW_SESSION_TICKET,
@@ -596,29 +746,26 @@ _gnutls_recv_new_session_ticket (gnutls_session_t session)
   p += 2;
 
   DECR_LENGTH_COM (data_size, ticket_len, goto error);
-  session->security_parameters.extensions.session_ticket =
-    gnutls_realloc (session->security_parameters.extensions.session_ticket,
-                   ticket_len);
-  if (!session->security_parameters.extensions.session_ticket)
+  priv->session_ticket = gnutls_realloc (priv->session_ticket, ticket_len);
+  if (!priv->session_ticket)
     {
       gnutls_assert ();
       gnutls_free (data);
       return GNUTLS_E_MEMORY_ERROR;
     }
-  memcpy (session->security_parameters.extensions.session_ticket,
-         p, ticket_len);
+  memcpy (priv->session_ticket, p, ticket_len);
   gnutls_free (data);
-  session->security_parameters.extensions.session_ticket_len = ticket_len;
+  priv->session_ticket_len = ticket_len;
 
   /* Discard the current session ID.  (RFC5077 3.4) */
   ret = _gnutls_generate_session_id (session->security_parameters.session_id,
-                                    &session->
-                                    security_parameters.session_id_size);
+                                    
&session->security_parameters.session_id_size);
   if (ret < 0)
     {
       gnutls_assert ();
       gnutls_free (data);
-      gnutls_free (session->security_parameters.extensions.session_ticket);
+      gnutls_free (priv->session_ticket);
+      priv->session_ticket = NULL;
       return GNUTLS_E_INTERNAL_ERROR;
     }
   return 0;
diff --git a/lib/ext_session_ticket.h b/lib/ext_session_ticket.h
index 85a5180..e8a531b 100644
--- a/lib/ext_session_ticket.h
+++ b/lib/ext_session_ticket.h
@@ -22,15 +22,17 @@
  *
  */
 
-#ifdef ENABLE_SESSION_TICKET
+#ifndef EXT_SESSION_TICKET_H
+# define EXT_SESSION_TICKET_H
 
-int _gnutls_session_ticket_recv_params (gnutls_session_t session,
-                                       const opaque * data,
-                                       size_t data_size);
-int _gnutls_session_ticket_send_params (gnutls_session_t session,
-                                       opaque * data, size_t data_size);
+# ifdef ENABLE_SESSION_TICKET
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_session_ticket;
 
 int _gnutls_send_new_session_ticket (gnutls_session_t session, int again);
 int _gnutls_recv_new_session_ticket (gnutls_session_t session);
 
+# endif
 #endif
diff --git a/lib/ext_signature.c b/lib/ext_signature.c
index e41e785..6936ff0 100644
--- a/lib/ext_signature.c
+++ b/lib/ext_signature.c
@@ -35,6 +35,33 @@
 #include <gnutls_num.h>
 #include <gnutls_algorithms.h>
 
+static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
+                                            const opaque * data,
+                                            size_t data_size);
+static int _gnutls_signature_algorithm_send_params (gnutls_session_t session,
+                                            opaque * data, size_t);
+static void signature_algorithms_deinit_data(extension_priv_data_t priv);
+static int signature_algorithms_pack(extension_priv_data_t epriv, 
gnutls_buffer_st* ps);
+static int signature_algorithms_unpack(gnutls_buffer_st* ps, 
extension_priv_data_t* _priv);
+
+extension_entry_st ext_mod_sig = {
+    .name = "SIGNATURE ALGORITHMS",
+    .type = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+    .parse_type = GNUTLS_EXT_TLS,
+
+    .recv_func = _gnutls_signature_algorithm_recv_params,
+    .send_func = _gnutls_signature_algorithm_send_params,
+    .pack_func = signature_algorithms_pack,
+    .unpack_func = signature_algorithms_unpack,
+    .deinit_func = signature_algorithms_deinit_data,
+};
+
+typedef struct {
+  /* TLS 1.2 signature algorithms */
+  gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS];
+  uint16_t sign_algorithms_size;
+} sig_ext_st;
+
 /* generates a SignatureAndHashAlgorithm structure with length as prefix
  * by using the setup priorities.
  */
@@ -70,6 +97,7 @@ _gnutls_sign_algorithm_write_params (gnutls_session_t 
session, opaque * data,
   return len + 2;
 }
 
+
 /* Parses the Signature Algorithm structure and stores data into
  * session->security_parameters.extensions.
  */
@@ -78,8 +106,15 @@ _gnutls_sign_algorithm_parse_data (gnutls_session_t session,
                                   const opaque * data, size_t data_size)
 {
   int sig, i;
+  sig_ext_st * priv;
+  extension_priv_data_t epriv;
 
-  session->security_parameters.extensions.sign_algorithms_size = 0;
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+       gnutls_assert();
+       return GNUTLS_E_MEMORY_ERROR;
+    }
 
   for (i = 0; i < data_size; i += 2)
     {
@@ -91,16 +126,16 @@ _gnutls_sign_algorithm_parse_data (gnutls_session_t 
session,
       sig = _gnutls_tls_aid_to_sign (&aid);
       if (sig != GNUTLS_SIGN_UNKNOWN)
        {
-         session->security_parameters.extensions.sign_algorithms[session->
-                                                                 
security_parameters.
-                                                                 
extensions.sign_algorithms_size++]
+         priv->sign_algorithms[priv->sign_algorithms_size++]
            = sig;
-         if (session->security_parameters.extensions.sign_algorithms_size ==
-             MAX_SIGNATURE_ALGORITHMS)
+         if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS)
            break;
        }
     }
 
+  epriv.ptr = priv;    
+  _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, 
epriv);
+
   return 0;
 }
 
@@ -113,7 +148,7 @@ _gnutls_sign_algorithm_parse_data (gnutls_session_t session,
  * then it is an error;
  */
 
-int
+static int
 _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
                                         const opaque * data,
                                         size_t _data_size)
@@ -139,7 +174,6 @@ _gnutls_signature_algorithm_recv_params (gnutls_session_t 
session,
        {
          uint16_t len;
 
-
          DECR_LEN (data_size, 2);
          len = _gnutls_read_uint16 (data);
          DECR_LEN (data_size, len);
@@ -158,7 +192,7 @@ _gnutls_signature_algorithm_recv_params (gnutls_session_t 
session,
 
 /* returns data_size or a negative number on failure
  */
-int
+static int
 _gnutls_signature_algorithm_send_params (gnutls_session_t session,
                                         opaque * data, size_t data_size)
 {
@@ -196,11 +230,22 @@ _gnutls_session_get_sign_algo (gnutls_session_t session,
                               gnutls_digest_algorithm_t * hash)
 {
   unsigned i;
+  int ret;
   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
+  sig_ext_st * priv;
+  extension_priv_data_t epriv;
 
+  ret = _gnutls_ext_get_session_data(session, 
GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+    &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
 
   if (!_gnutls_version_has_selectable_sighash (ver)
-      || session->security_parameters.extensions.sign_algorithms_size == 0)
+      || priv->sign_algorithms_size == 0)
     /* none set, allow all */
     {
       *hash = GNUTLS_DIG_SHA1;
@@ -208,15 +253,14 @@ _gnutls_session_get_sign_algo (gnutls_session_t session,
     }
 
   for (i = 0;
-       i < session->security_parameters.extensions.sign_algorithms_size; i++)
+       i < priv->sign_algorithms_size; i++)
     {
       if (_gnutls_sign_get_pk_algorithm
-         (session->security_parameters.extensions.sign_algorithms[i]) == pk)
+         (priv->sign_algorithms[i]) == pk)
        {
          *hash =
-           _gnutls_sign_get_hash_algorithm (session->security_parameters.
-                                            extensions.sign_algorithms[i]);
-         return session->security_parameters.extensions.sign_algorithms[i];
+           _gnutls_sign_get_hash_algorithm (priv->sign_algorithms[i]);
+         return priv->sign_algorithms[i];
        }
     }
 
@@ -233,19 +277,31 @@ _gnutls_session_sign_algo_requested (gnutls_session_t 
session,
                                     gnutls_sign_algorithm_t sig)
 {
   unsigned i;
+  int ret;
   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
+  sig_ext_st * priv;
+  extension_priv_data_t epriv;
+
+  ret = _gnutls_ext_get_session_data(session, 
GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+    &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
 
   if (!_gnutls_version_has_selectable_sighash (ver)
-      || session->security_parameters.extensions.sign_algorithms_size == 0)
+      || priv->sign_algorithms_size == 0)
     /* none set, allow all */
     {
       return 0;
     }
 
   for (i = 0;
-       i < session->security_parameters.extensions.sign_algorithms_size; i++)
+       i < priv->sign_algorithms_size; i++)
     {
-      if (session->security_parameters.extensions.sign_algorithms[i] == sig)
+      if (priv->sign_algorithms[i] == sig)
        {
          return 0;             /* ok */
        }
@@ -263,10 +319,22 @@ _gnutls_session_sign_algo_enabled (gnutls_session_t 
session,
                                   gnutls_sign_algorithm_t sig)
 {
   unsigned i;
+  int ret;
   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
+  sig_ext_st * priv;
+  extension_priv_data_t epriv;
+
+  ret = _gnutls_ext_get_session_data(session, 
GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+    &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return 0;
+    }
+  priv = epriv.ptr;
 
   if (!_gnutls_version_has_selectable_sighash (ver)
-      || session->security_parameters.extensions.sign_algorithms_size == 0)
+      || priv->sign_algorithms_size == 0)
     /* none set, allow all */
     {
       return 0;
@@ -283,6 +351,55 @@ _gnutls_session_sign_algo_enabled (gnutls_session_t 
session,
   return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
 }
 
+static void signature_algorithms_deinit_data(extension_priv_data_t priv)
+{
+    gnutls_free(priv.ptr);
+}
+
+static int signature_algorithms_pack(extension_priv_data_t epriv, 
gnutls_buffer_st* ps)
+{
+sig_ext_st* priv = epriv.ptr;
+int ret, i;
+
+  BUFFER_APPEND_NUM(ps, priv->sign_algorithms_size);
+  for (i = 0; i < priv->sign_algorithms_size;i++)
+    {
+      BUFFER_APPEND_NUM(ps, priv->sign_algorithms[i]);
+    }
+  return 0;
+}
+
+static int signature_algorithms_unpack(gnutls_buffer_st* ps, 
extension_priv_data_t* _priv)
+{
+sig_ext_st* priv;
+int i, ret;
+extension_priv_data_t epriv;
+
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+      gnutls_assert();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  BUFFER_POP_NUM(ps, priv->sign_algorithms_size);
+  for (i = 0; i < priv->sign_algorithms_size;i++)
+    {
+      BUFFER_POP_NUM(ps, priv->sign_algorithms[i]);
+    }
+
+  epriv.ptr = priv;
+  *_priv = epriv;
+  
+  return 0;
+
+error:
+  gnutls_free(priv);
+  return ret;
+}
+
+
+
 /**
  * gnutls_sign_algorithm_get_requested:
  * @session: is a #gnutls_session_t structure.
@@ -310,16 +427,28 @@ gnutls_sign_algorithm_get_requested (gnutls_session_t 
session,
                                     gnutls_sign_algorithm_t * algo)
 {
   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
+  sig_ext_st * priv;
+  extension_priv_data_t epriv;
+  int ret;
+
+  ret = _gnutls_ext_get_session_data(session, 
GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
+    &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
 
   if (!_gnutls_version_has_selectable_sighash (ver)
-      || session->security_parameters.extensions.sign_algorithms_size == 0)
+      || priv->sign_algorithms_size == 0)
     {
       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     }
 
-  if (indx < session->security_parameters.extensions.sign_algorithms_size)
+  if (indx < priv->sign_algorithms_size)
     {
-      *algo = session->security_parameters.extensions.sign_algorithms[indx];
+      *algo = priv->sign_algorithms[indx];
       return 0;
     }
   else
diff --git a/lib/ext_signature.h b/lib/ext_signature.h
index 69a05b7..2e41b60 100644
--- a/lib/ext_signature.h
+++ b/lib/ext_signature.h
@@ -25,11 +25,13 @@
 
 /* signature algorithms extension
  */
-int _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
-                                            const opaque * data,
-                                            size_t data_size);
-int _gnutls_signature_algorithm_send_params (gnutls_session_t session,
-                                            opaque * data, size_t);
+#ifndef EXT_SIGNATURE_H
+# define EXT_SIGNATURE_H
+
+#include <gnutls_extensions.h>
+
+extern extension_entry_st ext_mod_sig;
+
 int _gnutls_session_sign_algo_requested (gnutls_session_t session,
                                         gnutls_sign_algorithm_t sig);
 gnutls_sign_algorithm_t _gnutls_session_get_sign_algo (gnutls_session_t
@@ -44,3 +46,5 @@ int _gnutls_sign_algorithm_write_params (gnutls_session_t 
session,
                                         opaque * data, size_t max_data_size);
 int _gnutls_session_sign_algo_enabled (gnutls_session_t session,
                                       gnutls_sign_algorithm_t sig);
+
+#endif
diff --git a/lib/ext_srp.c b/lib/ext_srp.c
index 650e27e..7c36de0 100644
--- a/lib/ext_srp.c
+++ b/lib/ext_srp.c
@@ -33,14 +33,37 @@
 #include "gnutls_errors.h"
 #include "gnutls_algorithms.h"
 #include <gnutls_num.h>
+#include <gnutls_extensions.h>
 
-int
+static int _gnutls_srp_unpack(gnutls_buffer_st* ps, extension_priv_data_t* 
_priv);
+static int _gnutls_srp_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps);
+static void _gnutls_srp_deinit_data(extension_priv_data_t epriv);
+static int _gnutls_srp_recv_params (gnutls_session_t state, const opaque * 
data,
+                            size_t data_size);
+static int _gnutls_srp_send_params (gnutls_session_t state, opaque * data, 
size_t);
+
+extension_entry_st ext_mod_srp = {
+    .name = "SRP",
+    .type = GNUTLS_EXTENSION_SRP,
+    .parse_type = GNUTLS_EXT_TLS,
+
+    .recv_func = _gnutls_srp_recv_params,
+    .send_func = _gnutls_srp_send_params,
+    .pack_func = _gnutls_srp_pack,
+    .unpack_func = _gnutls_srp_unpack,
+    .deinit_func = _gnutls_srp_deinit_data
+};
+
+
+static int
 _gnutls_srp_recv_params (gnutls_session_t session, const opaque * data,
                         size_t _data_size)
 {
   uint8_t len;
   ssize_t data_size = _data_size;
-
+  extension_priv_data_t epriv;
+  srp_ext_st * priv;
+  
   if (session->security_parameters.entity == GNUTLS_SERVER)
     {
       if (data_size > 0)
@@ -53,10 +76,24 @@ _gnutls_srp_recv_params (gnutls_session_t session, const 
opaque * data,
              gnutls_assert ();
              return GNUTLS_E_ILLEGAL_SRP_USERNAME;
            }
-         memcpy (session->security_parameters.extensions.srp_username,
-                 &data[1], len);
-         /* null terminated */
-         session->security_parameters.extensions.srp_username[len] = 0;
+       
+         priv = gnutls_calloc(1, sizeof(*priv));
+         if (priv == NULL)
+           {
+             gnutls_assert();
+             return GNUTLS_E_MEMORY_ERROR;
+           }
+
+         priv->username = gnutls_malloc(len+1);
+         if (priv->username)
+           {
+             memcpy (priv->username, &data[1], len);
+             /* null terminated */
+             priv->username[len] = 0;
+           }
+
+         epriv.ptr = priv;
+         _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SRP, epriv);
        }
     }
   return 0;
@@ -65,11 +102,13 @@ _gnutls_srp_recv_params (gnutls_session_t session, const 
opaque * data,
 /* returns data_size or a negative number on failure
  * data is allocated locally
  */
-int
+static int
 _gnutls_srp_send_params (gnutls_session_t session, opaque * data,
                         size_t data_size)
 {
   unsigned len;
+  extension_priv_data_t epriv;
+  srp_ext_st * priv;
 
   if (_gnutls_kx_priority (session, GNUTLS_KX_SRP) < 0 &&
       _gnutls_kx_priority (session, GNUTLS_KX_SRP_DSS) < 0 &&
@@ -126,8 +165,18 @@ _gnutls_srp_send_params (gnutls_session_t session, opaque 
* data,
              return GNUTLS_E_SHORT_MEMORY_BUFFER;
            }
 
-         session->internals.srp_username = username;
-         session->internals.srp_password = password;
+         priv = gnutls_malloc(sizeof(*priv));
+         if (priv == NULL)
+           {
+             gnutls_assert();
+             return GNUTLS_E_MEMORY_ERROR;
+           }
+
+         priv->username = username;
+         priv->password = password;
+
+         epriv.ptr = priv;
+         _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_SRP, epriv);
 
          data[0] = (uint8_t) len;
          memcpy (&data[1], username, len);
@@ -137,4 +186,63 @@ _gnutls_srp_send_params (gnutls_session_t session, opaque 
* data,
   return 0;
 }
 
+static void _gnutls_srp_deinit_data(extension_priv_data_t epriv)
+{
+    srp_ext_st * priv = epriv.ptr;
+
+    gnutls_free(priv->username);
+    gnutls_free(priv->password);
+    gnutls_free(priv);
+}
+
+static int _gnutls_srp_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+srp_ext_st* priv = epriv.ptr;
+int ret;
+int password_len = 0, username_len = 0;
+
+  if (priv->username)
+    username_len = strlen(priv->username);
+
+  if (priv->password)
+    password_len = strlen(priv->password);
+
+  BUFFER_APPEND_PFX(ps, priv->username, username_len);
+  BUFFER_APPEND_PFX(ps, priv->password, password_len);
+
+  return 0;
+}
+
+static int _gnutls_srp_unpack(gnutls_buffer_st* ps, extension_priv_data_t* 
_priv)
+{
+srp_ext_st* priv;
+int ret;
+extension_priv_data_t epriv;
+gnutls_datum username = { NULL, 0 }, password = {NULL, 0};
+
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+      gnutls_assert();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  BUFFER_POP_DATUM(ps, &username);
+  BUFFER_POP_DATUM(ps, &password);
+  
+  priv->username = username.data;
+  priv->password = password.data;
+  
+  epriv.ptr = priv;
+  *_priv = epriv;
+  
+  return 0;
+
+error:
+  _gnutls_free_datum(&username);
+  _gnutls_free_datum(&password);
+  return ret;
+}
+
+
 #endif /* ENABLE_SRP */
diff --git a/lib/ext_srp.h b/lib/ext_srp.h
index 4491823..a1146b0 100644
--- a/lib/ext_srp.h
+++ b/lib/ext_srp.h
@@ -23,13 +23,23 @@
  *
  */
 
-#ifdef ENABLE_SRP
+#ifndef EXT_SRP_H
+#define EXT_SRP_H
 
-#define IS_SRP_KX(kx) ((kx == GNUTLS_KX_SRP || (kx == GNUTLS_KX_SRP_RSA) || \
+#include <gnutls_extensions.h>
+
+# ifdef ENABLE_SRP
+
+#  define IS_SRP_KX(kx) ((kx == GNUTLS_KX_SRP || (kx == GNUTLS_KX_SRP_RSA) || \
           kx == GNUTLS_KX_SRP_DSS)?1:0)
 
-int _gnutls_srp_recv_params (gnutls_session_t state, const opaque * data,
-                            size_t data_size);
-int _gnutls_srp_send_params (gnutls_session_t state, opaque * data, size_t);
+extern extension_entry_st ext_mod_srp;
+
+typedef struct {
+    char* username;
+    char* password;
+} srp_ext_st;
+
+# endif
 
 #endif
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 58d2f6a..78aa8b7 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -127,7 +127,7 @@ _gnutls_record_buffer_put (content_type_t type,
                           gnutls_session_t session, opaque * data,
                           size_t length)
 {
-  gnutls_buffer *buf;
+  gnutls_buffer_st *buf;
 
   if (length == 0)
     return 0;
@@ -157,7 +157,7 @@ _gnutls_record_buffer_put (content_type_t type,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  if (_gnutls_buffer_append (buf, data, length) < 0)
+  if (_gnutls_buffer_append_data (buf, data, length) < 0)
     {
       gnutls_assert ();
       return GNUTLS_E_MEMORY_ERROR;
@@ -218,14 +218,14 @@ _gnutls_record_buffer_get (content_type_t type,
   switch (type)
     {
     case GNUTLS_APPLICATION_DATA:
-      _gnutls_buffer_get_data (&session->internals.application_data_buffer,
+      _gnutls_buffer_pop_data (&session->internals.application_data_buffer,
                               data, &length);
       _gnutls_buffers_log ("BUFFER[REC][AD]: Read %d bytes of Data(%d)\n",
                           (int) length, (int) type);
       break;
 
     case GNUTLS_HANDSHAKE:
-      _gnutls_buffer_get_data (&session->internals.handshake_data_buffer,
+      _gnutls_buffer_pop_data (&session->internals.handshake_data_buffer,
                               data, &length);
       _gnutls_buffers_log ("BUF[REC][HD]: Read %d bytes of Data(%d)\n",
                           (int) length, (int) type);
@@ -233,7 +233,7 @@ _gnutls_record_buffer_get (content_type_t type,
 
     case GNUTLS_INNER_APPLICATION:
 
-      _gnutls_buffer_get_data (&session->internals.ia_data_buffer, data,
+      _gnutls_buffer_pop_data (&session->internals.ia_data_buffer, data,
                               &length);
       _gnutls_buffers_log ("BUF[REC][IA]: Read %d bytes of Data(%d)\n",
                           (int) length, (int) type);
@@ -839,14 +839,14 @@ _gnutls_handshake_io_recv_int (gnutls_session_t session,
          gnutls_assert ();
 
          tmp = sizeOfPtr;
-         _gnutls_string_get_data (&session->internals.handshake_recv_buffer,
+         _gnutls_buffer_pop_data (&session->internals.handshake_recv_buffer,
                                   iptr, &tmp);
          return tmp;
        }
       gnutls_assert ();
 
       tmp = sizeOfPtr;
-      _gnutls_string_get_data (&session->internals.handshake_recv_buffer,
+      _gnutls_buffer_pop_data (&session->internals.handshake_recv_buffer,
                               iptr, &tmp);
       left -= tmp;
 
@@ -865,7 +865,7 @@ _gnutls_handshake_io_recv_int (gnutls_session_t session,
            {
              gnutls_assert ();
 
-             _gnutls_buffer_append (&session->internals.
+             _gnutls_buffer_append_data (&session->internals.
                                     handshake_recv_buffer, iptr, dsize);
 
              session->internals.handshake_recv_buffer_htype = htype;
@@ -910,7 +910,7 @@ _gnutls_handshake_buffer_put (gnutls_session_t session, 
opaque * data,
     }
 
   _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data\n", (int) length);
-  if (_gnutls_buffer_append (&session->internals.handshake_hash_buffer,
+  if (_gnutls_buffer_append_data (&session->internals.handshake_hash_buffer,
                             data, length) < 0)
     {
       gnutls_assert ();
diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c
index f6d58cc..b91abc4 100644
--- a/lib/gnutls_constate.c
+++ b/lib/gnutls_constate.c
@@ -35,6 +35,7 @@
 #include <gnutls_num.h>
 #include <gnutls_datum.h>
 #include <gnutls_state.h>
+#include <gnutls_extensions.h>
 
 static const char keyexp[] = "key expansion";
 static const int keyexp_length = sizeof (keyexp) - 1;
@@ -381,13 +382,6 @@ _gnutls_set_write_keys (gnutls_session_t session)
                           export_flag);
 }
 
-#define CPY_EXTENSIONS \
-        gnutls_free(dst->extensions.session_ticket); \
-        gnutls_free(dst->extensions.oprfi_client); \
-        gnutls_free(dst->extensions.oprfi_server); \
-       memcpy(&dst->extensions.server_names, &src->extensions, 
sizeof(src->extensions)); \
-       memset(&src->extensions, 0, sizeof(src->extensions))    /* avoid 
duplicate free's */
-
 #define CPY_COMMON dst->entity = src->entity; \
        dst->kx_algorithm = src->kx_algorithm; \
        memcpy( &dst->current_cipher_suite, &src->current_cipher_suite, 
sizeof(cipher_suite_st)); \
@@ -400,8 +394,7 @@ _gnutls_set_write_keys (gnutls_session_t session)
        dst->timestamp = src->timestamp; \
        dst->max_record_recv_size = src->max_record_recv_size; \
        dst->max_record_send_size = src->max_record_send_size; \
-       dst->version = src->version; \
-       memcpy( &dst->inner_secret, &src->inner_secret, GNUTLS_MASTER_SIZE)
+       dst->version = src->version
 
 static void
 _gnutls_cpy_read_security_parameters (security_parameters_st *
@@ -419,7 +412,6 @@ _gnutls_cpy_write_security_parameters 
(security_parameters_st *
                                       dst, security_parameters_st * src)
 {
   CPY_COMMON;
-  CPY_EXTENSIONS;              /* only do once */
 
   dst->write_bulk_cipher_algorithm = src->write_bulk_cipher_algorithm;
   dst->write_mac_algorithm = src->write_mac_algorithm;
@@ -493,7 +485,7 @@ _gnutls_read_connection_state_init (gnutls_session_t 
session)
        return rc;
     }
   else
-    {                          /* RESUME_TRUE */
+    { /* RESUME_TRUE */
       _gnutls_cpy_read_security_parameters (&session->security_parameters,
                                            &session->
                                            
internals.resumed_security_parameters);
@@ -681,6 +673,7 @@ _gnutls_write_connection_state_init (gnutls_session_t 
session)
       _gnutls_cpy_write_security_parameters (&session->security_parameters,
                                             &session->
                                             
internals.resumed_security_parameters);
+      _gnutls_ext_restore_resumed_session(session);
     }
 
   rc = _gnutls_set_write_keys (session);
diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c
index 9a1b8f9..f316d5c 100644
--- a/lib/gnutls_extensions.c
+++ b/lib/gnutls_extensions.c
@@ -34,7 +34,6 @@
 #include "ext_max_record.h"
 #include <ext_cert_type.h>
 #include <ext_server_name.h>
-#include <ext_oprfi.h>
 #include <ext_srp.h>
 #include <ext_session_ticket.h>
 #include <ext_safe_renegotiation.h>
@@ -42,28 +41,26 @@
 #include <ext_safe_renegotiation.h>
 #include <gnutls_num.h>
 
-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;
+static void _gnutls_ext_unset_resumed_session_data(gnutls_session_t session, 
uint16_t type);
 
-  /* 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_extension_entry;
 
 static size_t extfunc_size = 0;
-static gnutls_extension_entry *extfunc = NULL;
+static extension_entry_st *extfunc = NULL;
+
+static gnutls_ext_parse_type_t 
+_gnutls_ext_parse_type (uint16_t type)
+{
+  size_t i;
+
+  for (i = 0; i < extfunc_size; i++)
+    {
+      if (extfunc[i].type == type)
+        return extfunc[i].parse_type;
+    }
+
+  return GNUTLS_EXT_NONE;
+}
 
 static gnutls_ext_recv_func
 _gnutls_ext_func_recv (uint16_t type, gnutls_ext_parse_type_t parse_type)
@@ -78,6 +75,31 @@ _gnutls_ext_func_recv (uint16_t type, 
gnutls_ext_parse_type_t parse_type)
   return NULL;
 }
 
+static gnutls_ext_deinit_data_func
+_gnutls_ext_func_deinit (uint16_t type)
+{
+  size_t i;
+
+  for (i = 0; i < extfunc_size; i++)
+    if (extfunc[i].type == type)
+       return extfunc[i].deinit_func;
+
+  return NULL;
+}
+
+static gnutls_ext_unpack_func
+_gnutls_ext_func_unpack (uint16_t type)
+{
+  size_t i;
+
+  for (i = 0; i < extfunc_size; i++)
+    if (extfunc[i].type == type)
+       return extfunc[i].unpack_func;
+
+  return NULL;
+}
+
+
 static const char *
 _gnutls_extension_get_name (uint16_t type)
 {
@@ -236,7 +258,7 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * 
data,
   pos += 2;
   for (i = 0; i < extfunc_size; i++)
     {
-      gnutls_extension_entry *p = &extfunc[i];
+      extension_entry_st *p = &extfunc[i];
 
       if (p->send_func == NULL)
        continue;
@@ -272,8 +294,8 @@ _gnutls_gen_extensions (gnutls_session_t session, opaque * 
data,
           */
          _gnutls_extension_list_add (session, p->type);
 
-         _gnutls_debug_log ("EXT[%p]: Sending extension %s\n",
-                            session, p->name);
+         _gnutls_debug_log ("EXT[%p]: Sending extension %s (%d bytes)\n",
+                            session, p->name, size);
        }
       else if (size < 0)
        {
@@ -303,73 +325,37 @@ _gnutls_ext_init (void)
 {
   int ret;
 
-  ret = gnutls_ext_register (GNUTLS_EXTENSION_MAX_RECORD_SIZE,
-                            "MAX_RECORD_SIZE",
-                            GNUTLS_EXT_TLS,
-                            _gnutls_max_record_recv_params,
-                            _gnutls_max_record_send_params);
+  ret = _gnutls_ext_register (&ext_mod_max_record_size);
   if (ret != GNUTLS_E_SUCCESS)
     return ret;
 
-  ret = gnutls_ext_register (GNUTLS_EXTENSION_CERT_TYPE,
-                            "CERT_TYPE",
-                            GNUTLS_EXT_TLS,
-                            _gnutls_cert_type_recv_params,
-                            _gnutls_cert_type_send_params);
+  ret = _gnutls_ext_register (&ext_mod_cert_type);
   if (ret != GNUTLS_E_SUCCESS)
     return ret;
 
-  ret = gnutls_ext_register (GNUTLS_EXTENSION_SERVER_NAME,
-                            "SERVER_NAME",
-                            GNUTLS_EXT_APPLICATION,
-                            _gnutls_server_name_recv_params,
-                            _gnutls_server_name_send_params);
-  if (ret != GNUTLS_E_SUCCESS)
-    return ret;
 
-  ret = gnutls_ext_register (GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
-                            "SAFE_RENEGOTIATION",
-                            GNUTLS_EXT_MANDATORY,
-                            _gnutls_safe_renegotiation_recv_params,
-                            _gnutls_safe_renegotiation_send_params);
+  ret = _gnutls_ext_register (&ext_mod_server_name);
   if (ret != GNUTLS_E_SUCCESS)
     return ret;
 
-#ifdef ENABLE_OPRFI
-  ret = gnutls_ext_register (GNUTLS_EXTENSION_OPAQUE_PRF_INPUT,
-                            "OPAQUE_PRF_INPUT",
-                            GNUTLS_EXT_TLS,
-                            _gnutls_oprfi_recv_params,
-                            _gnutls_oprfi_send_params);
+  ret = _gnutls_ext_register (&ext_mod_sr);
   if (ret != GNUTLS_E_SUCCESS)
     return ret;
-#endif
 
 #ifdef ENABLE_SRP
-  ret = gnutls_ext_register (GNUTLS_EXTENSION_SRP,
-                            "SRP",
-                            GNUTLS_EXT_TLS,
-                            _gnutls_srp_recv_params,
-                            _gnutls_srp_send_params);
+  ret = _gnutls_ext_register (&ext_mod_srp);
   if (ret != GNUTLS_E_SUCCESS)
     return ret;
 #endif
 
+
 #ifdef ENABLE_SESSION_TICKET
-  ret = gnutls_ext_register (GNUTLS_EXTENSION_SESSION_TICKET,
-                            "SESSION_TICKET",
-                            GNUTLS_EXT_TLS,
-                            _gnutls_session_ticket_recv_params,
-                            _gnutls_session_ticket_send_params);
+  ret = _gnutls_ext_register (&ext_mod_session_ticket);
   if (ret != GNUTLS_E_SUCCESS)
     return ret;
 #endif
 
-  ret = gnutls_ext_register (GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
-                            "SIGNATURE_ALGORITHMS",
-                            GNUTLS_EXT_TLS,
-                            _gnutls_signature_algorithm_recv_params,
-                            _gnutls_signature_algorithm_send_params);
+  ret = _gnutls_ext_register (&ext_mod_sig);
   if (ret != GNUTLS_E_SUCCESS)
     return ret;
 
@@ -384,6 +370,27 @@ _gnutls_ext_deinit (void)
   extfunc_size = 0;
 }
 
+int
+_gnutls_ext_register (extension_entry_st* mod)
+{
+  extension_entry_st *p;
+
+  p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
+  if (!p)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  extfunc = p;
+
+  memcpy(&extfunc[extfunc_size], mod, sizeof(*mod));
+
+  extfunc_size++;
+
+  return GNUTLS_E_SUCCESS;
+}
+
 /**
  * gnutls_ext_register:
  * @type: the 16-bit integer referring to the extension type
@@ -405,23 +412,288 @@ gnutls_ext_register (int type,
                     gnutls_ext_recv_func recv_func,
                     gnutls_ext_send_func send_func)
 {
-  gnutls_extension_entry *p;
+extension_entry_st ee;
+
+  memset(&ee, 0, sizeof(ee));
+  
+  ee.type = type;
+  ee.name = name;
+  ee.parse_type = parse_type;
+  ee.recv_func = recv_func;
+  ee.send_func = send_func;
+    /* FIXME: Why is this exported? Should it be removed? */
+  return _gnutls_ext_register (&ee);
+}
 
-  p = gnutls_realloc (extfunc, sizeof (*extfunc) * (extfunc_size + 1));
-  if (!p)
+int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st* packed)
+{
+int i, ret;
+extension_priv_data_t data;
+int cur_size;
+void* size_pos;
+void* total_exts_pos;
+int exts = 0;
+
+  total_exts_pos = packed->data + packed->length;
+  
+  BUFFER_APPEND_NUM(packed, 0);
+
+  for (i = 0; i < extfunc_size; i++) 
     {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
+      ret = _gnutls_ext_get_session_data(session, extfunc[i].type, &data);
+      if (ret >= 0 && extfunc[i].pack_func != NULL) 
+        {
+         BUFFER_APPEND_NUM(packed, extfunc[i].type);
+         
+         size_pos = packed->data + packed->length;
+         
+         BUFFER_APPEND_NUM(packed, 0);
+         
+         cur_size = packed->length;
+         
+         ret = extfunc[i].pack_func(data, packed);
+         if (ret < 0) 
+           {
+             gnutls_assert();
+             return ret;
+           }
+         
+         exts++;
+         /* write the actual size */
+         _gnutls_write_uint32(packed->length-cur_size, size_pos);
+        }
     }
-  extfunc = p;
 
-  extfunc[extfunc_size].type = type;
-  extfunc[extfunc_size].name = name;
-  extfunc[extfunc_size].parse_type = parse_type;
-  extfunc[extfunc_size].recv_func = recv_func;
-  extfunc[extfunc_size].send_func = send_func;
+  _gnutls_write_uint32(exts, total_exts_pos);
 
-  extfunc_size++;
+  return 0;
+    
+}
 
-  return GNUTLS_E_SUCCESS;
+void _gnutls_ext_restore_resumed_session(gnutls_session_t session)
+{
+int i;
+
+
+  /* clear everything except MANDATORY extensions */
+  for (i=0;i<MAX_EXT_TYPES;i++) 
+    {
+      if (session->internals.extension_int_data[i].set != 0 && 
+          
_gnutls_ext_parse_type(session->internals.extension_int_data[i].type) != 
GNUTLS_EXT_MANDATORY)
+        {
+          _gnutls_ext_unset_session_data(session, 
session->internals.extension_int_data[i].type);
+        }
+    }
+
+  /* copy resumed to main */
+  for (i=0;i<MAX_EXT_TYPES;i++) 
+    {
+      if (session->internals.resumed_extension_int_data[i].set != 0 && 
+          
_gnutls_ext_parse_type(session->internals.resumed_extension_int_data[i].type) 
!= GNUTLS_EXT_MANDATORY)
+        {
+          _gnutls_ext_set_session_data(session, 
session->internals.resumed_extension_int_data[i].type, 
+              session->internals.resumed_extension_int_data[i].priv);
+          session->internals.resumed_extension_int_data[i].set = 0;
+        }
+    }
+
+}
+
+
+static void _gnutls_ext_set_resumed_session_data(gnutls_session_t session, 
uint16_t type, 
+    extension_priv_data_t data)
+{
+int i;
+
+  for (i=0;i<MAX_EXT_TYPES;i++) 
+    {
+      if (session->internals.resumed_extension_int_data[i].type == type)
+       {
+           
+           if (session->internals.resumed_extension_int_data[i].set != 0)
+             _gnutls_ext_unset_resumed_session_data(session, type);
+
+           session->internals.resumed_extension_int_data[i].type = type;
+           session->internals.resumed_extension_int_data[i].priv = data;
+           session->internals.resumed_extension_int_data[i].set = 1;
+           return;
+        }
+    }
+}
+
+int _gnutls_ext_unpack(gnutls_session_t session, gnutls_buffer_st* packed)
+{
+int i, ret;
+extension_priv_data_t data;
+gnutls_ext_unpack_func unpack;
+int max_exts = 0;
+uint16_t type;
+int size_for_type, cur_pos;
+
+  BUFFER_POP_NUM(packed, max_exts);
+  for (i = 0; i < max_exts; i++) 
+    {
+      BUFFER_POP_NUM(packed, type);
+      BUFFER_POP_NUM(packed, size_for_type);
+    
+      cur_pos = packed->length;
+
+      unpack = _gnutls_ext_func_unpack(type);
+      if (unpack == NULL)
+        {
+         gnutls_assert();
+         return GNUTLS_E_PARSING_ERROR;
+       }
+    
+      ret = unpack(packed, &data);
+      if (ret < 0) 
+       {
+         gnutls_assert();
+         return ret;
+       }
+      
+      /* verify that unpack read the correct bytes */
+      cur_pos = cur_pos - packed->length;
+      if (cur_pos /* read length */ != size_for_type)
+        {
+         gnutls_assert();
+         return GNUTLS_E_PARSING_ERROR;
+       }
+      _gnutls_ext_set_resumed_session_data(session, type, data);
+    }
+
+  return 0;
+
+error:
+  return ret;    
+}
+
+void _gnutls_ext_unset_session_data(gnutls_session_t session, uint16_t type)
+{
+gnutls_ext_deinit_data_func deinit;
+extension_priv_data_t data;
+int ret, i;
+
+  deinit = _gnutls_ext_func_deinit (type);
+  ret = _gnutls_ext_get_session_data(session, type, &data);
+
+  if (ret >= 0 && deinit != NULL)
+    {
+       deinit(data);
+    }
+
+  for (i=0;i<MAX_EXT_TYPES;i++) 
+    {
+      if (session->internals.extension_int_data[i].type == type)
+       {
+         session->internals.extension_int_data[i].set = 0;
+         return;
+        }
+    }
+
+}
+
+static void _gnutls_ext_unset_resumed_session_data(gnutls_session_t session, 
uint16_t type)
+{
+gnutls_ext_deinit_data_func deinit;
+extension_priv_data_t data;
+int ret, i;
+
+  deinit = _gnutls_ext_func_deinit (type);
+  ret = _gnutls_ext_get_resumed_session_data(session, type, &data);
+
+  if (ret >= 0 && deinit != NULL)
+    {
+       deinit(data);
+    }
+
+  for (i=0;i<MAX_EXT_TYPES;i++) 
+    {
+      if (session->internals.resumed_extension_int_data[i].type == type)
+       {
+         session->internals.resumed_extension_int_data[i].set = 0;
+         return;
+        }
+    }
+
+}
+
+/* Deinitializes all data that are associated with TLS extensions.
+ */
+void _gnutls_ext_free_session_data(gnutls_session_t session)
+{
+int i;
+
+  for (i = 0; i < extfunc_size; i++) 
+    {
+      _gnutls_ext_unset_session_data(session, extfunc[i].type);
+    }
+
+  for (i = 0; i < extfunc_size; i++) 
+    {
+      _gnutls_ext_unset_resumed_session_data(session, extfunc[i].type);
+    }
+
+}
+
+/* This function allows and extension to store data in the current session
+ * and retrieve them later on. We use functions instead of a pointer to a
+ * private pointer, to allow API additions by individual extensions.
+ */
+void _gnutls_ext_set_session_data(gnutls_session_t session, uint16_t type, 
+    extension_priv_data_t data)
+{
+int i;
+gnutls_ext_deinit_data_func deinit;
+
+  deinit = _gnutls_ext_func_deinit (type);
+
+  for (i=0;i<MAX_EXT_TYPES;i++) 
+    {
+      if (session->internals.extension_int_data[i].type == type || 
session->internals.extension_int_data[i].set == 0)
+       {
+           if (session->internals.extension_int_data[i].set != 0)
+             {
+               if (deinit) 
deinit(session->internals.extension_int_data[i].priv);
+             }
+           session->internals.extension_int_data[i].type = type;
+           session->internals.extension_int_data[i].priv = data;
+           session->internals.extension_int_data[i].set = 1;
+           return;
+        }
+    }
+}
+
+int _gnutls_ext_get_session_data(gnutls_session_t session, 
+    uint16_t type, extension_priv_data_t* data)
+{
+int i;
+
+  for (i=0;i<MAX_EXT_TYPES;i++) 
+    {
+      if (session->internals.extension_int_data[i].set != 0 &&
+        session->internals.extension_int_data[i].type == type)
+       {
+           *data = session->internals.extension_int_data[i].priv;
+           return 0;
+        }
+    }
+  return GNUTLS_E_INVALID_REQUEST;
+}
+
+int _gnutls_ext_get_resumed_session_data(gnutls_session_t session, 
+    uint16_t type, extension_priv_data_t* data)
+{
+int i;
+
+  for (i=0;i<MAX_EXT_TYPES;i++) 
+    {
+      if (session->internals.resumed_extension_int_data[i].set != 0 && 
+        session->internals.resumed_extension_int_data[i].type == type)
+       {
+           *data = session->internals.resumed_extension_int_data[i].priv;
+           return 0;
+        }
+    }
+  return GNUTLS_E_INVALID_REQUEST;
 }
diff --git a/lib/gnutls_extensions.h b/lib/gnutls_extensions.h
index 6c6f891..3c450e8 100644
--- a/lib/gnutls_extensions.h
+++ b/lib/gnutls_extensions.h
@@ -23,6 +23,9 @@
  *
  */
 
+#ifndef GNUTLS_EXTENSIONS_H
+#define GNUTLS_EXTENSIONS_H
+
 int _gnutls_parse_extensions (gnutls_session_t session,
                              gnutls_ext_parse_type_t parse_type,
                              const opaque * data, int data_size);
@@ -32,3 +35,56 @@ int _gnutls_ext_init (void);
 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);
+
+void _gnutls_ext_free_session_data(gnutls_session_t session);
+
+/* functions to be used by extensions internally
+ */
+void _gnutls_ext_unset_session_data(gnutls_session_t session, uint16_t type);
+void _gnutls_ext_set_session_data(gnutls_session_t session, uint16_t type, 
+    extension_priv_data_t);
+int _gnutls_ext_get_session_data(gnutls_session_t session, 
+    uint16_t type, extension_priv_data_t*);
+int _gnutls_ext_get_resumed_session_data(gnutls_session_t session,
+    uint16_t type, extension_priv_data_t* data);
+
+void _gnutls_ext_restore_resumed_session(gnutls_session_t session);
+
+/* for session packing */
+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 */
+  
+} extension_entry_st;
+
+int _gnutls_ext_register (extension_entry_st*);
+
+#endif
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index ecdee2f..278c7c6 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -697,27 +697,12 @@ _gnutls_send_finished (gnutls_session_t session, int 
again)
       if (session->internals.finished_func)
        session->internals.finished_func (session, data, vdata_size);
 
-      /* Save data for safe renegotiation. 
-       */
-      if (vdata_size > MAX_VERIFY_DATA_SIZE)
-       {
-         gnutls_assert ();
-         return GNUTLS_E_INTERNAL_ERROR;
-       }
-
-       if (session->security_parameters.entity == GNUTLS_CLIENT)
-         {
-           session->security_parameters.extensions.client_verify_data_len =
-           vdata_size;
-
-           memcpy (session->security_parameters.extensions.client_verify_data, 
data, vdata_size);
-         }
-       else
-         {
-           session->security_parameters.extensions.server_verify_data_len = 
vdata_size;
-           memcpy (session->security_parameters.extensions.server_verify_data,
-             data, vdata_size);
-         }
+      ret = _gnutls_ext_sr_finished( session, data, vdata_size, 0);
+      if (ret < 0)
+        {
+         gnutls_assert();
+         return ret;
+       }
 
       ret = _gnutls_send_handshake (session, bufel, GNUTLS_HANDSHAKE_FINISHED);
     }
@@ -739,7 +724,6 @@ _gnutls_recv_finished (gnutls_session_t session)
   int data_size;
   int ret;
   int vrfysize;
-  tls_ext_st *ext;
 
   ret =
     _gnutls_recv_handshake (session, &vrfy, &vrfysize,
@@ -797,24 +781,11 @@ _gnutls_recv_finished (gnutls_session_t session)
     }
   gnutls_free (vrfy);
 
-  /* Save peer's verify data for safe renegotiation */
-  if (data_size > MAX_VERIFY_DATA_SIZE)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
-    }
-
-  ext = &session->security_parameters.extensions;
-
-  if (session->security_parameters.entity == GNUTLS_CLIENT)
-    {
-      memcpy (ext->server_verify_data, data, data_size);
-      ext->server_verify_data_len = data_size;
-    }
-  else
+  ret = _gnutls_ext_sr_finished( session, data, data_size, 1);
+  if (ret < 0)
     {
-      memcpy (ext->client_verify_data, data, data_size);
-      ext->client_verify_data_len = data_size;
+      gnutls_assert();
+      return ret;
     }
 
   session->internals.initial_negotiation_completed = 1;
@@ -886,8 +857,12 @@ _gnutls_server_select_suite (gnutls_session_t session, 
opaque * data,
          {
            _gnutls_handshake_log
              ("HSK[%p]: Received safe renegotiation CS\n", session);
-           session->internals.safe_renegotiation_received = 1;
-           session->internals.connection_using_safe_renegotiation = 1;
+           retval = _gnutls_ext_sr_recv_cs(session);
+           if (retval < 0)
+             {
+               gnutls_assert();
+               return retval;
+             }
            break;
          }
       }
@@ -1938,7 +1913,7 @@ _gnutls_copy_comp_methods (gnutls_session_t session,
 /* This should be sufficient by now. It should hold all the extensions
  * plus the headers in a hello message.
  */
-#define MAX_EXT_DATA_LENGTH 1024
+#define MAX_EXT_DATA_LENGTH 4096
 
 /* This function sends the client hello handshake message.
  */
@@ -1976,10 +1951,7 @@ _gnutls_send_client_hello (gnutls_session_t session, int 
again)
          return GNUTLS_E_MEMORY_ERROR;
        }
       data = _mbuffer_get_udata_ptr(bufel);
-      extdatalen = MAX_EXT_DATA_LENGTH
-       +
-       session->internals.resumed_security_parameters.
-       extensions.session_ticket_len;
+      extdatalen = MAX_EXT_DATA_LENGTH;
 
       extdata = gnutls_malloc (extdatalen);
       if (extdata == NULL)
@@ -2079,7 +2051,7 @@ _gnutls_send_client_hello (gnutls_session_t session, int 
again)
 
       if (ret > 0)
        {
-         bufel = _mbuffer_append_data (bufel, extdata, ret);
+         bufel = _mbuffer_push_data (bufel, extdata, ret);
          if (bufel == NULL)
            {
              gnutls_assert ();
@@ -2103,7 +2075,7 @@ _gnutls_send_client_hello (gnutls_session_t session, int 
again)
       ret = _gnutls_copy_comp_methods (session, extdata, extdatalen);
       if (ret > 0)
        {
-         bufel = _mbuffer_append_data (bufel, extdata, ret);
+         bufel = _mbuffer_push_data (bufel, extdata, ret);
          if (bufel == NULL)
            {
              gnutls_assert ();
@@ -2137,7 +2109,7 @@ _gnutls_send_client_hello (gnutls_session_t session, int 
again)
 
       if (ret > 0)
        {
-         bufel = _mbuffer_append_data (bufel, extdata, ret);
+         bufel = _mbuffer_push_data (bufel, extdata, ret);
          if (bufel == NULL)
            {
              gnutls_assert ();
@@ -2176,28 +2148,6 @@ _gnutls_send_server_hello (gnutls_session_t session, int 
again)
 
   datalen = 0;
 
-#ifdef ENABLE_SRP
-  if (IS_SRP_KX
-      (_gnutls_cipher_suite_get_kx_algo
-       (&session->security_parameters.current_cipher_suite)))
-    {
-      /* While resuming we cannot check the username extension since it is
-       * not available at this point. It will be copied on connection
-       * state activation.
-       */
-      if (session->internals.resumed == RESUME_FALSE &&
-         session->security_parameters.extensions.srp_username[0] == 0)
-       {
-         /* The peer didn't send a valid SRP extension with the
-          * SRP username. The draft requires that we send a fatal
-          * alert and abort.
-          */
-         gnutls_assert ();
-         return GNUTLS_E_UNKNOWN_SRP_USERNAME;
-       }
-    }
-#endif
-
   if (again == 0)
     {
       datalen = 2 + session_id_len + 1 + GNUTLS_RANDOM_SIZE + 3;
@@ -2269,8 +2219,6 @@ _gnutls_send_hello (gnutls_session_t session, int again)
 {
   int ret;
 
-  session->internals.safe_renegotiation_received = 0;
-
   if (session->security_parameters.entity == GNUTLS_CLIENT)
     {
       ret = _gnutls_send_client_hello (session, again);
@@ -2292,7 +2240,6 @@ int
 _gnutls_recv_hello (gnutls_session_t session, opaque * data, int datalen)
 {
   int ret;
-  tls_ext_st *ext;
 
   if (session->security_parameters.entity == GNUTLS_CLIENT)
     {
@@ -2314,101 +2261,14 @@ _gnutls_recv_hello (gnutls_session_t session, opaque * 
data, int datalen)
        }
     }
 
-  if (session->internals.priorities.sr == SR_DISABLED)
-    {
-      gnutls_assert ();
-      return ret;
-    }
-
-  /* Safe renegotiation */
-  ext = &session->security_parameters.extensions;
-
-  if (session->internals.safe_renegotiation_received)
-    {
-      if ((ext->ri_extension_data_len < ext->client_verify_data_len) ||
-         (memcmp (ext->ri_extension_data,
-                  ext->client_verify_data, ext->client_verify_data_len)))
-       {
-         gnutls_assert ();
-         _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
-                                session);
-         return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
-       }
-
-      if (session->security_parameters.entity == GNUTLS_CLIENT)
-       {
-         if ((ext->ri_extension_data_len !=
-              ext->client_verify_data_len + ext->server_verify_data_len) ||
-             memcmp (ext->ri_extension_data + ext->client_verify_data_len,
-                     ext->server_verify_data,
-                     ext->server_verify_data_len) != 0)
-           {
-             gnutls_assert ();
-             _gnutls_handshake_log
-               ("HSK[%p]: Safe renegotiation failed [2]\n", session);
-             return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
-           }
-       }
-      else                     /* Make sure there are 0 extra bytes */
-       {
-         if (ext->ri_extension_data_len != ext->client_verify_data_len)
-           {
-             gnutls_assert ();
-             _gnutls_handshake_log
-               ("HSK[%p]: Safe renegotiation failed [3]\n", session);
-             return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
-           }
-       }
-
-      _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n",
-                            session);
-    }
-  else /* safe renegotiation not received... */
+  ret = _gnutls_ext_sr_verify(session);
+  if (ret < 0)
     {
-      if (session->internals.connection_using_safe_renegotiation)
-       {
-         gnutls_assert ();
-         _gnutls_handshake_log
-           ("HSK[%p]: Peer previously asked for safe renegotiation\n",
-            session);
-         return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
-       }
-
-      /* Clients can't tell if it's an initial negotiation */
-      if (session->internals.initial_negotiation_completed)
-       {
-
-          if (session->internals.priorities.sr < SR_PARTIAL)
-           {
-             _gnutls_handshake_log
-               ("HSK[%p]: Allowing unsafe (re)negotiation\n", session);
-           }
-         else
-           {
-             gnutls_assert ();
-             _gnutls_handshake_log
-               ("HSK[%p]: Denying unsafe (re)negotiation\n", session);
-              return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED;
-           }
-       }
-      else
-       {
-         if (session->internals.priorities.sr < SR_SAFE)
-           {
-             _gnutls_handshake_log
-               ("HSK[%p]: Allowing unsafe initial negotiation\n", session);
-           }
-         else
-           {
-             gnutls_assert ();
-             _gnutls_handshake_log
-               ("HSK[%p]: Denying unsafe initial negotiation\n", session);
-             return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
-           }
-       }
+       gnutls_assert();
+       return ret;
     }
 
-  return ret;
+  return 0;
 }
 
 /* The packets in gnutls_handshake (it's more broad than original TLS 
handshake)
@@ -2590,7 +2450,7 @@ _gnutls_send_supplemental (gnutls_session_t session, int 
again)
     ret = _gnutls_send_handshake (session, NULL, 
GNUTLS_HANDSHAKE_SUPPLEMENTAL);
   else
     {
-      gnutls_buffer buf;
+      gnutls_buffer_st buf;
       _gnutls_buffer_init (&buf);
 
       ret = _gnutls_gen_supplemental (session, &buf);
@@ -2767,7 +2627,7 @@ _gnutls_handshake_client (gnutls_session_t session)
       IMED_RET ("recv hello", ret, 1);
 
     case STATE70:
-      if (session->security_parameters.extensions.do_recv_supplemental)
+      if (session->security_parameters.do_recv_supplemental)
        {
          ret = _gnutls_recv_supplemental (session);
          STATE = STATE70;
@@ -2808,7 +2668,7 @@ _gnutls_handshake_client (gnutls_session_t session)
       IMED_RET ("recv server hello done", ret, 1);
 
     case STATE71:
-      if (session->security_parameters.extensions.do_send_supplemental)
+      if (session->security_parameters.do_send_supplemental)
        {
          ret = _gnutls_send_supplemental (session, AGAIN (STATE71));
          STATE = STATE71;
@@ -2867,7 +2727,6 @@ _gnutls_send_handshake_final (gnutls_session_t session, 
int init)
          gnutls_assert ();
          return ret;
        }
-
       /* Initialize the connection session (start encryption) - in case of 
client 
        */
       if (init == TRUE)
@@ -2991,7 +2850,7 @@ _gnutls_handshake_server (gnutls_session_t session)
       IMED_RET ("send hello", ret, 0);
 
     case STATE70:
-      if (session->security_parameters.extensions.do_send_supplemental)
+      if (session->security_parameters.do_send_supplemental)
        {
          ret = _gnutls_send_supplemental (session, AGAIN (STATE70));
          STATE = STATE70;
@@ -3033,7 +2892,7 @@ _gnutls_handshake_server (gnutls_session_t session)
       IMED_RET ("send server hello done", ret, 0);
 
     case STATE71:
-      if (session->security_parameters.extensions.do_recv_supplemental)
+      if (session->security_parameters.do_recv_supplemental)
        {
          ret = _gnutls_recv_supplemental (session);
          STATE = STATE71;
@@ -3091,13 +2950,9 @@ _gnutls_handshake_common (gnutls_session_t session)
        {
        case STATE0:
        case STATE40:
-         if (session->internals.session_ticket_renew)
-           {
-             ret =
-               _gnutls_send_new_session_ticket (session, AGAIN (STATE40));
-             STATE = STATE40;
-             IMED_RET ("send handshake new session ticket", ret, 0);
-           }
+          ret = _gnutls_send_new_session_ticket (session, AGAIN (STATE40));
+          STATE = STATE40;
+          IMED_RET ("send handshake new session ticket", ret, 0);
          STATE = STATE0;
        default:
          break;
@@ -3125,12 +2980,9 @@ _gnutls_handshake_common (gnutls_session_t session)
        {
        case STATE0:
        case STATE41:
-         if (session->internals.session_ticket_renew)
-           {
-             ret = _gnutls_recv_new_session_ticket (session);
-             STATE = STATE41;
-             IMED_RET ("recv handshake new session ticket", ret, 1);
-           }
+          ret = _gnutls_recv_new_session_ticket (session);
+         STATE = STATE41;
+         IMED_RET ("recv handshake new session ticket", ret, 1);
          STATE = STATE0;
        default:
          break;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index d317486..b099f11 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -95,7 +95,7 @@ typedef struct
 
 /* we can receive up to MAX_EXT_TYPES extensions.
  */
-#define MAX_EXT_TYPES 64
+#define MAX_EXT_TYPES 32
 
 /* The initial size of the receive
  * buffer size. This will grow if larger
@@ -172,9 +172,6 @@ typedef enum extensions_t
 { GNUTLS_EXTENSION_SERVER_NAME = 0,
   GNUTLS_EXTENSION_MAX_RECORD_SIZE = 1,
   GNUTLS_EXTENSION_CERT_TYPE = 9,
-#ifdef ENABLE_OPRFI
-  GNUTLS_EXTENSION_OPAQUE_PRF_INPUT = ENABLE_OPRFI,
-#endif
   GNUTLS_EXTENSION_SRP = 12,
   GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS = 13,
   GNUTLS_EXTENSION_SESSION_TICKET = 35,
@@ -185,12 +182,8 @@ typedef enum extensions_t
 typedef enum
 { CIPHER_STREAM, CIPHER_BLOCK } cipher_type_t;
 
-typedef enum valid_session_t
-{ VALID_TRUE, VALID_FALSE } valid_session_t;
-typedef enum resumable_session_t
-{ RESUME_TRUE,
-  RESUME_FALSE
-} resumable_session_t;
+#define RESUME_TRUE 0
+#define RESUME_FALSE -1
 
 /* Record Protocol */
 typedef enum content_type_t
@@ -315,69 +308,10 @@ typedef struct
  * structures also - see SRP).
  */
 
-typedef struct
-{
-  opaque name[MAX_SERVER_NAME_SIZE];
-  unsigned name_length;
-  gnutls_server_name_type_t type;
-} server_name_st;
-
-#define MAX_SERVER_NAME_EXTENSIONS 3
 #define MAX_SIGNATURE_ALGORITHMS 16
 
-struct gnutls_session_ticket_key_st
-{
-  opaque key_name[SESSION_TICKET_KEY_NAME_SIZE];
-  opaque key[SESSION_TICKET_KEY_SIZE];
-  opaque mac_secret[SESSION_TICKET_MAC_SECRET_SIZE];
-};
-
 #define MAX_VERIFY_DATA_SIZE 36        /* in SSL 3.0, 12 in TLS 1.0 */
 
-/* If you want the extension data to be kept across resuming sessions
- * then modify CPY_EXTENSIONS in gnutls_constate.c
- */
-typedef struct
-{
-  server_name_st server_names[MAX_SERVER_NAME_EXTENSIONS];
-  /* limit server_name extensions */
-  unsigned server_names_size;
-
-  opaque srp_username[MAX_SRP_USERNAME + 1];
-
-  /* TLS 1.2 signature algorithms */
-  gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS];
-  uint16_t sign_algorithms_size;
-
-  /* TLS/IA data. */
-  int gnutls_ia_enable, gnutls_ia_peer_enable;
-  int gnutls_ia_allowskip, gnutls_ia_peer_allowskip;
-
-  /* Used by extensions that enable supplemental data. */
-  int do_recv_supplemental, do_send_supplemental;
-
-  opaque *session_ticket;
-  uint16_t session_ticket_len;
-
-  /*** Those below do not get copied when resuming session 
-   ***/
-
-  /* Opaque PRF input. */
-  opaque *oprfi_client;
-  uint16_t oprfi_client_len;
-  opaque *oprfi_server;
-  uint16_t oprfi_server_len;
-
-  /* Safe renegotiation. */
-  uint8_t client_verify_data[MAX_VERIFY_DATA_SIZE];
-  size_t client_verify_data_len;
-  uint8_t server_verify_data[MAX_VERIFY_DATA_SIZE];
-  size_t server_verify_data_len;
-  uint8_t ri_extension_data[MAX_VERIFY_DATA_SIZE * 2]; /* max signal is 72 
bytes in s->c sslv3 */
-  size_t ri_extension_data_len;
-
-} tls_ext_st;
-
 /* auth_info_t structures now MAY contain malloced 
  * elements.
  */
@@ -424,7 +358,6 @@ typedef struct
   opaque session_id[TLS_MAX_SESSION_ID_SIZE];
   uint8_t session_id_size;
   time_t timestamp;
-  tls_ext_st extensions;
 
   /* The send size is the one requested by the programmer.
    * The recv size is the one negotiated with the peer.
@@ -435,8 +368,14 @@ typedef struct
   gnutls_certificate_type_t cert_type;
   gnutls_protocol_t version;   /* moved here */
 
-  /* For TLS/IA.  XXX: Move to IA credential? */
-  opaque inner_secret[GNUTLS_MASTER_SIZE];
+  /* FIXME: The following are not saved in the session storage
+   * for session resumption.
+   */
+
+  /* Used by extensions that enable supplemental data: Which ones
+   * do that? Do they belong in security parameters?
+   */
+  int do_recv_supplemental, do_send_supplemental;
 } security_parameters_st;
 
 /* This structure holds the generated keys
@@ -529,11 +468,16 @@ typedef struct
   gnutls_handshake_description_t recv_type;
 } handshake_header_buffer_st;
 
+typedef union 
+{
+  void* ptr;
+  uint32_t num;
+} extension_priv_data_t;
 
 typedef struct
 {
-  gnutls_buffer application_data_buffer;       /* holds data to be delivered 
to application layer */
-  gnutls_buffer handshake_hash_buffer; /* used to keep the last received 
handshake 
+  gnutls_buffer_st application_data_buffer;    /* holds data to be delivered 
to application layer */
+  gnutls_buffer_st handshake_hash_buffer;      /* used to keep the last 
received handshake 
                                         * message */
   union
   {
@@ -550,9 +494,9 @@ typedef struct
   } handshake_mac_handle;
   int handshake_mac_handle_init;       /* 1 when the previous union and type 
were initialized */
 
-  gnutls_buffer handshake_data_buffer; /* this is a buffer that holds the 
current handshake message */
-  gnutls_buffer ia_data_buffer;        /* holds inner application data 
(TLS/IA) */
-  resumable_session_t resumable;       /* TRUE or FALSE - if we can resume 
that session */
+  gnutls_buffer_st handshake_data_buffer;      /* this is a buffer that holds 
the current handshake message */
+  gnutls_buffer_st ia_data_buffer;     /* holds inner application data 
(TLS/IA) */
+  int resumable:1;     /* TRUE or FALSE - if we can resume that session */
   handshake_state_t handshake_state;   /* holds
                                         * a number which indicates where
                                         * the handshake procedure has been
@@ -560,12 +504,12 @@ typedef struct
                                         * no interruption has happened.
                                         */
 
-  valid_session_t valid_connection;    /* true or FALSE - if this session is 
valid */
+  int invalid_connection:1;    /* true or FALSE - if this session is valid */
 
-  int may_not_read;            /* if it's 0 then we can read/write, otherwise 
it's forbiden to read/write
+  int may_not_read:1;          /* if it's 0 then we can read/write, otherwise 
it's forbiden to read/write
                                 */
-  int may_not_write;
-  int read_eof;                        /* non-zero if we have received a 
closure alert. */
+  int may_not_write:1;
+  int read_eof:1;                      /* non-zero if we have received a 
closure alert. */
 
   int last_alert;              /* last alert received */
 
@@ -581,7 +525,7 @@ typedef struct
   struct gnutls_priority_st priorities;
 
   /* resumed session */
-  resumable_session_t resumed; /* RESUME_TRUE or FALSE - if we are resuming a 
session */
+  int resumed:1;       /* RESUME_TRUE or FALSE - if we are resuming a session 
*/
   security_parameters_st resumed_security_parameters;
 
   /* sockets internals */
@@ -594,12 +538,12 @@ typedef struct
   gnutls_handshake_description_t handshake_send_buffer_htype;
   content_type_t handshake_recv_buffer_type;
   gnutls_handshake_description_t handshake_recv_buffer_htype;
-  gnutls_buffer handshake_recv_buffer;
+  gnutls_buffer_st handshake_recv_buffer;
 
   /* this buffer holds a record packet -mostly used for
    * non blocking IO.
    */
-  gnutls_buffer record_recv_buffer;
+  gnutls_buffer_st record_recv_buffer;
   mbuffer_head_st record_send_buffer;  /* holds cached data
                                         * for the gnutls_io_write_buffered()
                                         * function.
@@ -607,7 +551,7 @@ typedef struct
 
   /* 0 if no peeked data was kept, 1 otherwise.
    */
-  int have_peeked_data;
+  int have_peeked_data:1;
 
   int expire_time;             /* after expire_time seconds this session will 
expire */
   struct mod_auth_st_int *auth_struct; /* used in handshake packets and KX 
algorithms */
@@ -662,11 +606,6 @@ typedef struct
    */
   gnutls_handshake_post_client_hello_func user_hello_func;
 
-  /* Holds the record size requested by the
-   * user.
-   */
-  uint16_t proposed_record_size;
-
   /* holds the selected certificate and key.
    * use _gnutls_selected_certs_deinit() and _gnutls_selected_certs_set()
    * to change them.
@@ -674,7 +613,7 @@ typedef struct
   gnutls_cert *selected_cert_list;
   int selected_cert_list_length;
   struct gnutls_privkey_st *selected_key;
-  int selected_need_free;
+  int selected_need_free:1;
 
   /* holds the extensions we sent to the peer
    * (in case of a client)
@@ -691,8 +630,6 @@ typedef struct
    * record packet will have. */
   opaque default_record_version[2];
 
-  int cbc_protection_hack;
-
   void *user_ptr;
 
   int enable_private;          /* non zero to
@@ -721,9 +658,6 @@ typedef struct
    */
   opaque rsa_pms_version[2];
 
-  char *srp_username;
-  char *srp_password;
-
   /* Here we cache the DH or RSA parameters got from the
    * credentials structure, or from a callback. That is to
    * minimize external calls.
@@ -759,19 +693,19 @@ typedef struct
    */
   uint16_t srp_prime_bits;
 
-  int session_ticket_enable, session_ticket_renew;
-
-  int safe_renegotiation_received:1;
   int initial_negotiation_completed:1;
-  int connection_using_safe_renegotiation:1;
-
-  /* Oprfi */
-  gnutls_oprfi_callback_func oprfi_cb;
-  const void *oprfi_userdata;
 
-  /* Session Ticket */
-  struct gnutls_session_ticket_key_st *session_ticket_key;
-  opaque session_ticket_IV[SESSION_TICKET_IV_SIZE];
+  struct {
+      uint16_t type;
+      extension_priv_data_t priv;
+      int set:1;
+  } extension_int_data[MAX_EXT_TYPES];
+
+  struct {
+      uint16_t type;
+      extension_priv_data_t priv;
+      int set:1;
+  } resumed_extension_int_data[MAX_EXT_TYPES];
 
   /* If you add anything here, check _gnutls_handshake_internal_state_clear().
    */
diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c
index 9d3cae9..9f1f5a7 100644
--- a/lib/gnutls_kx.c
+++ b/lib/gnutls_kx.c
@@ -39,6 +39,7 @@
 #include <gnutls_datum.h>
 #include <gnutls_rsa_export.h>
 #include <gnutls_mbuffers.h>
+#include "../libextra/ext_inner_application.h" /* isn't this too much? */
 
 /* This is a temporary function to be used before the generate_*
    internal API is changed to use mbuffers. For now we don't avoid the
@@ -123,64 +124,6 @@ generate_normal_master (gnutls_session_t session, int 
keep_premaster)
                                      security_parameters.master_secret);
 
     }
-  else if (session->security_parameters.extensions.oprfi_client_len > 0 &&
-          session->security_parameters.extensions.oprfi_server_len > 0)
-    {
-      opaque *rnd;
-      size_t rndlen = 2 * GNUTLS_RANDOM_SIZE;
-
-      rndlen += session->security_parameters.extensions.oprfi_client_len;
-      rndlen += session->security_parameters.extensions.oprfi_server_len;
-
-      rnd = gnutls_malloc (rndlen + 1);
-      if (!rnd)
-       {
-         gnutls_assert ();
-         return GNUTLS_E_MEMORY_ERROR;
-       }
-
-      _gnutls_hard_log ("INT: CLIENT OPRFI[%d]: %s\n",
-                       session->security_parameters.extensions.
-                       oprfi_server_len,
-                       _gnutls_bin2hex (session->
-                                        security_parameters.extensions.
-                                        oprfi_client,
-                                        session->
-                                        security_parameters.extensions.
-                                        oprfi_client_len, buf,
-                                        sizeof (buf), NULL));
-      _gnutls_hard_log ("INT: SERVER OPRFI[%d]: %s\n",
-                       session->security_parameters.extensions.
-                       oprfi_server_len,
-                       _gnutls_bin2hex (session->
-                                        security_parameters.extensions.
-                                        oprfi_server,
-                                        session->
-                                        security_parameters.extensions.
-                                        oprfi_server_len, buf,
-                                        sizeof (buf), NULL));
-
-      memcpy (rnd, session->security_parameters.client_random,
-             GNUTLS_RANDOM_SIZE);
-      memcpy (rnd + GNUTLS_RANDOM_SIZE,
-             session->security_parameters.extensions.oprfi_client,
-             session->security_parameters.extensions.oprfi_client_len);
-      memcpy (rnd + GNUTLS_RANDOM_SIZE +
-             session->security_parameters.extensions.oprfi_client_len,
-             session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
-      memcpy (rnd + GNUTLS_RANDOM_SIZE +
-             session->security_parameters.extensions.oprfi_client_len +
-             GNUTLS_RANDOM_SIZE,
-             session->security_parameters.extensions.oprfi_server,
-             session->security_parameters.extensions.oprfi_server_len);
-
-      ret = _gnutls_PRF (session, PREMASTER.data, PREMASTER.size,
-                        MASTER_SECRET, strlen (MASTER_SECRET),
-                        rnd, rndlen, GNUTLS_MASTER_SIZE,
-                        session->security_parameters.master_secret);
-
-      gnutls_free (rnd);
-    }
   else
     {
       opaque rnd[2 * GNUTLS_RANDOM_SIZE + 1];
@@ -198,8 +141,7 @@ generate_normal_master (gnutls_session_t session, int 
keep_premaster)
     }
 
   /* TLS/IA inner secret is derived from the master secret. */
-  memcpy (session->security_parameters.inner_secret,
-         session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
+  _gnutls_ia_derive_inner_secret(session);
 
   if (!keep_premaster)
     _gnutls_free_datum (&PREMASTER);
diff --git a/lib/gnutls_mbuffers.c b/lib/gnutls_mbuffers.c
index 2c9e9d8..db9763b 100644
--- a/lib/gnutls_mbuffers.c
+++ b/lib/gnutls_mbuffers.c
@@ -152,7 +152,7 @@ _mbuffer_alloc (size_t payload_size)
 }
 
 mbuffer_st*
-_mbuffer_append_data (mbuffer_st *bufel, void* newdata, size_t newdata_size)
+_mbuffer_push_data (mbuffer_st *bufel, void* newdata, size_t newdata_size)
 {
   bufel = gnutls_realloc_fast (bufel, bufel->msg.size+newdata_size+sizeof 
(mbuffer_st));
   if (bufel == NULL)
diff --git a/lib/gnutls_mbuffers.h b/lib/gnutls_mbuffers.h
index a1a6065..3580a42 100644
--- a/lib/gnutls_mbuffers.h
+++ b/lib/gnutls_mbuffers.h
@@ -37,7 +37,7 @@ mbuffer_st* _mbuffer_alloc (size_t payload_size);
 /* This is dangerous since it will replace bufel with a new
  * one.
  */
-mbuffer_st* _mbuffer_append_data (mbuffer_st *bufel, void* newdata, size_t 
newdata_size);
+mbuffer_st* _mbuffer_push_data (mbuffer_st *bufel, void* newdata, size_t 
newdata_size);
 
 
 /* For "user" use. One can have buffer data and header.
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index a3a0409..c2c3a9b 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -273,7 +273,7 @@ gnutls_bye (gnutls_session_t session, 
gnutls_close_request_t how)
 inline static void
 session_invalidate (gnutls_session_t session)
 {
-  session->internals.valid_connection = VALID_FALSE;
+  session->internals.invalid_connection = 1;
 }
 
 
@@ -288,7 +288,7 @@ session_unresumable (gnutls_session_t session)
 inline static int
 session_is_valid (gnutls_session_t session)
 {
-  if (session->internals.valid_connection == VALID_FALSE)
+  if (session->internals.invalid_connection != 0)
     return GNUTLS_E_INVALID_SESSION;
 
   return 0;
@@ -1173,64 +1173,3 @@ gnutls_record_recv (gnutls_session_t session, void 
*data, size_t sizeofdata)
                           sizeofdata);
 }
 
-/**
- * gnutls_record_get_max_size:
- * @session: is a #gnutls_session_t structure.
- *
- * Get the record size.  The maximum record size is negotiated by the
- * client after the first handshake message.
- *
- * Returns: The maximum record packet size in this connection.
- **/
-size_t
-gnutls_record_get_max_size (gnutls_session_t session)
-{
-  /* Recv will hold the negotiated max record size
-   * always.
-   */
-  return session->security_parameters.max_record_recv_size;
-}
-
-
-/**
- * gnutls_record_set_max_size:
- * @session: is a #gnutls_session_t structure.
- * @size: is the new size
- *
- * This function sets the maximum record packet size in this
- * connection.  This property can only be set to clients.  The server
- * may choose not to accept the requested size.
- *
- * Acceptable values are 512(=2^9), 1024(=2^10), 2048(=2^11) and
- * 4096(=2^12).  The requested record size does get in effect
- * immediately only while sending data. The receive part will take
- * effect after a successful handshake.
- *
- * This function uses a TLS extension called 'max record size'.  Not
- * all TLS implementations use or even understand this extension.
- *
- * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
- *   otherwise an error code is returned.
- **/
-ssize_t
-gnutls_record_set_max_size (gnutls_session_t session, size_t size)
-{
-  ssize_t new_size;
-
-  if (session->security_parameters.entity == GNUTLS_SERVER)
-    return GNUTLS_E_INVALID_REQUEST;
-
-  new_size = _gnutls_mre_record2num (size);
-
-  if (new_size < 0)
-    {
-      gnutls_assert ();
-      return new_size;
-    }
-
-  session->security_parameters.max_record_send_size = size;
-
-  session->internals.proposed_record_size = size;
-
-  return 0;
-}
diff --git a/lib/gnutls_session_pack.c b/lib/gnutls_session_pack.c
index 0ca3b0c..03e7909 100644
--- a/lib/gnutls_session_pack.c
+++ b/lib/gnutls_session_pack.c
@@ -41,34 +41,33 @@
 #include <gnutls_session_pack.h>
 #include <gnutls_datum.h>
 #include <gnutls_num.h>
+#include <gnutls_extensions.h>
 
-#define PACK_HEADER_SIZE 1
-#define MAX_SEC_PARAMS 
7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)+165
 static int pack_certificate_auth_info (gnutls_session_t,
-                                      gnutls_datum_t * packed_session);
+                                      gnutls_buffer_st * packed_session);
 static int unpack_certificate_auth_info (gnutls_session_t,
-                                        const gnutls_datum_t *
+                                        gnutls_buffer_st *
                                         packed_session);
 
 static int unpack_srp_auth_info (gnutls_session_t session,
-                                const gnutls_datum_t * packed_session);
+                                gnutls_buffer_st * packed_session);
 static int pack_srp_auth_info (gnutls_session_t session,
-                              gnutls_datum_t * packed_session);
+                              gnutls_buffer_st * packed_session);
 
 static int unpack_psk_auth_info (gnutls_session_t session,
-                                const gnutls_datum_t * packed_session);
+                                gnutls_buffer_st * packed_session);
 static int pack_psk_auth_info (gnutls_session_t session,
-                              gnutls_datum_t * packed_session);
+                              gnutls_buffer_st * packed_session);
 
 static int unpack_anon_auth_info (gnutls_session_t session,
-                                 const gnutls_datum_t * packed_session);
+                                 gnutls_buffer_st * packed_session);
 static int pack_anon_auth_info (gnutls_session_t session,
-                               gnutls_datum_t * packed_session);
+                               gnutls_buffer_st * packed_session);
 
 static int unpack_security_parameters (gnutls_session_t session,
-                                      const gnutls_datum_t * packed_session);
+                                      gnutls_buffer_st * packed_session);
 static int pack_security_parameters (gnutls_session_t session,
-                                    gnutls_datum_t * packed_session);
+                                    gnutls_buffer_st * packed_session);
 
 
 /* Since auth_info structures contain malloced data, this function
@@ -84,6 +83,8 @@ _gnutls_session_pack (gnutls_session_t session,
                      gnutls_datum_t * packed_session)
 {
   int ret;
+  gnutls_buffer_st sb;
+  opaque id;
 
   if (packed_session == NULL)
     {
@@ -91,12 +92,16 @@ _gnutls_session_pack (gnutls_session_t session,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
+  _gnutls_buffer_init(&sb);
 
-  switch (gnutls_auth_get_type (session))
+  id = gnutls_auth_get_type (session);
+  BUFFER_APPEND(&sb, &id, 1);
+
+  switch (id)
     {
 #ifdef ENABLE_SRP
     case GNUTLS_CRD_SRP:
-      ret = pack_srp_auth_info (session, packed_session);
+      ret = pack_srp_auth_info (session, &sb);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -106,7 +111,7 @@ _gnutls_session_pack (gnutls_session_t session,
 #endif
 #ifdef ENABLE_PSK
     case GNUTLS_CRD_PSK:
-      ret = pack_psk_auth_info (session, packed_session);
+      ret = pack_psk_auth_info (session, &sb);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -116,7 +121,7 @@ _gnutls_session_pack (gnutls_session_t session,
 #endif
 #ifdef ENABLE_ANON
     case GNUTLS_CRD_ANON:
-      ret = pack_anon_auth_info (session, packed_session);
+      ret = pack_anon_auth_info (session, &sb);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -125,7 +130,7 @@ _gnutls_session_pack (gnutls_session_t session,
       break;
 #endif
     case GNUTLS_CRD_CERTIFICATE:
-      ret = pack_certificate_auth_info (session, packed_session);
+      ret = pack_certificate_auth_info (session, &sb);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -140,15 +145,25 @@ _gnutls_session_pack (gnutls_session_t session,
   /* Auth_info structures copied. Now copy security_parameters_st. 
    * packed_session must have allocated space for the security parameters.
    */
-  ret = pack_security_parameters (session, packed_session);
+  ret = pack_security_parameters (session, &sb);
   if (ret < 0)
     {
       gnutls_assert ();
-      _gnutls_free_datum (packed_session);
+      _gnutls_buffer_clear(&sb);
       return ret;
     }
-
-  return 0;
+    
+  ret = _gnutls_ext_pack(session, &sb);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      _gnutls_buffer_clear(&sb);
+      return ret;
+    }
+  
+  ret =  _gnutls_buffer_to_datum(&sb, packed_session);
+  
+  return ret;
 }
 
 
@@ -159,6 +174,10 @@ _gnutls_session_unpack (gnutls_session_t session,
                        const gnutls_datum_t * packed_session)
 {
   int ret;
+  gnutls_buffer_st sb;
+  opaque id;
+  
+  _gnutls_buffer_init(&sb);
 
   if (packed_session == NULL || packed_session->size == 0)
     {
@@ -166,36 +185,45 @@ _gnutls_session_unpack (gnutls_session_t session,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
+  ret = _gnutls_buffer_append_data(&sb, packed_session->data, 
packed_session->size);
+  if (ret < 0) 
+    {
+      gnutls_assert();
+      return ret;
+    }
+
   if (_gnutls_get_auth_info (session) != NULL)
     {
       _gnutls_free_auth_info (session);
     }
 
-  switch (packed_session->data[0])
+  BUFFER_POP(&sb, &id, 1);
+
+  switch (id)
     {
 #ifdef ENABLE_SRP
     case GNUTLS_CRD_SRP:
-      ret = unpack_srp_auth_info (session, packed_session);
+      ret = unpack_srp_auth_info (session, &sb);
       if (ret < 0)
        {
          gnutls_assert ();
-         return ret;
+         goto error;
        }
       break;
 #endif
 #ifdef ENABLE_PSK
     case GNUTLS_CRD_PSK:
-      ret = unpack_psk_auth_info (session, packed_session);
+      ret = unpack_psk_auth_info (session, &sb);
       if (ret < 0)
        {
          gnutls_assert ();
-         return ret;
+         goto error;
        }
       break;
 #endif
 #ifdef ENABLE_ANON
     case GNUTLS_CRD_ANON:
-      ret = unpack_anon_auth_info (session, packed_session);
+      ret = unpack_anon_auth_info (session, &sb);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -204,33 +232,47 @@ _gnutls_session_unpack (gnutls_session_t session,
       break;
 #endif
     case GNUTLS_CRD_CERTIFICATE:
-      ret = unpack_certificate_auth_info (session, packed_session);
+      ret = unpack_certificate_auth_info (session, &sb);
       if (ret < 0)
        {
          gnutls_assert ();
-         return ret;
+         goto error;
        }
       break;
     default:
       gnutls_assert ();
-      return GNUTLS_E_INTERNAL_ERROR;
+      ret = GNUTLS_E_INTERNAL_ERROR;
+      goto error;
 
     }
 
   /* Auth_info structures copied. Now copy security_parameters_st. 
    * packed_session must have allocated space for the security parameters.
    */
-  ret = unpack_security_parameters (session, packed_session);
+  ret = unpack_security_parameters (session, &sb);
   if (ret < 0)
     {
       gnutls_assert ();
-      return ret;
+      goto error;
+    }
+    
+  ret = _gnutls_ext_unpack(session, &sb);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto error;
     }
 
-  return 0;
+  ret = 0;
+
+error:
+  _gnutls_buffer_clear(&sb);
+  
+  return ret;
 }
 
 
+
 /* Format: 
  *      1 byte the credentials type
  *      4 bytes the size of the whole structure
@@ -255,78 +297,37 @@ _gnutls_session_unpack (gnutls_session_t session,
  */
 static int
 pack_certificate_auth_info (gnutls_session_t session,
-                           gnutls_datum_t * packed_session)
+                           gnutls_buffer_st * ps)
 {
-  unsigned int pos = 0, i;
-  int cert_size, pack_size;
+  unsigned int i;
+  int cur_size, ret;
   cert_auth_info_t info = _gnutls_get_auth_info (session);
+  void* size_pos;
 
-  if (info)
-    {
-      cert_size = 4;
+  size_pos = ps->data + ps->length; 
 
-      for (i = 0; i < info->ncerts; i++)
-       cert_size += 4 + info->raw_certificate_list[i].size;
-
-      pack_size = 2 + 4 + info->dh.prime.size +
-       4 + info->dh.generator.size + 4 + info->dh.public_key.size +
-       4 + info->rsa_export.modulus.size +
-       4 + info->rsa_export.exponent.size + cert_size;
-    }
-  else
-    pack_size = 0;
-
-  packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
-
-  /* calculate the size and allocate the data.
-   */
-  packed_session->data =
-    gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 +
-                  session->security_parameters.extensions.
-                  session_ticket_len);
+  BUFFER_APPEND_NUM(ps, 0);
+  cur_size = ps->length;
 
-  if (packed_session->data == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  packed_session->data[0] = GNUTLS_CRD_CERTIFICATE;
-  _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
-  pos += 4 + PACK_HEADER_SIZE;
-
-
-  if (pack_size > 0)
+  if (info)
     {
 
-      _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
-      pos += 2;
-
-      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
-      pos += 4 + info->dh.prime.size;
-      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
-      pos += 4 + info->dh.generator.size;
-      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
-      pos += 4 + info->dh.public_key.size;
+      BUFFER_APPEND_NUM( ps, info->dh.secret_bits);
+      BUFFER_APPEND_PFX( ps, info->dh.prime.data, info->dh.prime.size);
+      BUFFER_APPEND_PFX( ps, info->dh.generator.data, info->dh.generator.size);
+      BUFFER_APPEND_PFX( ps, info->dh.public_key.data, 
info->dh.public_key.size);
+      BUFFER_APPEND_PFX( ps, info->rsa_export.modulus.data, 
info->rsa_export.modulus.size);
+      BUFFER_APPEND_PFX( ps, info->rsa_export.exponent.data, 
info->rsa_export.exponent.size);
 
-      _gnutls_write_datum32 (&packed_session->data[pos],
-                            info->rsa_export.modulus);
-      pos += 4 + info->rsa_export.modulus.size;
-      _gnutls_write_datum32 (&packed_session->data[pos],
-                            info->rsa_export.exponent);
-      pos += 4 + info->rsa_export.exponent.size;
-
-      _gnutls_write_uint32 (info->ncerts, &packed_session->data[pos]);
-      pos += 4;
+      BUFFER_APPEND_NUM( ps, info->ncerts);
 
       for (i = 0; i < info->ncerts; i++)
-       {
-         _gnutls_write_datum32 (&packed_session->data[pos],
-                                info->raw_certificate_list[i]);
-         pos += sizeof (uint32_t) + info->raw_certificate_list[i].size;
-       }
+        BUFFER_APPEND_PFX( ps, info->raw_certificate_list[i].data, 
info->raw_certificate_list[i].size);
     }
 
+  /* write the real size */
+  _gnutls_write_uint32(ps->length-cur_size, size_pos);
+
   return 0;
 }
 
@@ -335,32 +336,18 @@ pack_certificate_auth_info (gnutls_session_t session,
  */
 static int
 unpack_certificate_auth_info (gnutls_session_t session,
-                             const gnutls_datum_t * packed_session)
+                             gnutls_buffer_st * ps)
 {
-  int pos = 0, size, ret;
-  unsigned int i = 0, j;
+  int ret;
+  unsigned int i = 0, j = 0;
   size_t pack_size;
-  cert_auth_info_t info;
-
-  if (packed_session->data[0] != GNUTLS_CRD_CERTIFICATE)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
+  cert_auth_info_t info = NULL;
 
-  pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
-  pos += PACK_HEADER_SIZE + 4;
+  BUFFER_POP_NUM(ps, pack_size);
 
   if (pack_size == 0)
     return 0;                  /* nothing to be done */
 
-  /* a simple check for integrity */
-  if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
   /* client and server have the same auth_info here
    */
   ret =
@@ -379,113 +366,49 @@ unpack_certificate_auth_info (gnutls_session_t session,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
-  info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]);
-  pos += 2;
-
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      goto error;
-    }
-  pos += size;
-
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret =
-    _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      goto error;
-    }
-  pos += size;
-
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret =
-    _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
-                      size);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      goto error;
-    }
-  pos += size;
-
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret =
-    _gnutls_set_datum (&info->rsa_export.modulus,
-                      &packed_session->data[pos], size);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      goto error;
-    }
-  pos += size;
+  BUFFER_POP_NUM(ps, info->dh.secret_bits);
 
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret =
-    _gnutls_set_datum (&info->rsa_export.exponent,
-                      &packed_session->data[pos], size);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      goto error;
-    }
-  pos += size;
+  BUFFER_POP_DATUM(ps, &info->dh.prime);
+  BUFFER_POP_DATUM(ps, &info->dh.generator);
+  BUFFER_POP_DATUM(ps, &info->dh.public_key);
+  BUFFER_POP_DATUM(ps, &info->rsa_export.modulus);
+  BUFFER_POP_DATUM(ps, &info->rsa_export.exponent);
 
-  info->ncerts = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
+  BUFFER_POP_NUM(ps, info->ncerts);
 
   if (info->ncerts > 0)
     {
-      info->raw_certificate_list =
-       gnutls_calloc (info->ncerts, sizeof (gnutls_datum_t));
+      info->raw_certificate_list = gnutls_calloc (info->ncerts, sizeof 
(gnutls_datum_t));
       if (info->raw_certificate_list == NULL)
-       {
-         gnutls_assert ();
-         ret = GNUTLS_E_MEMORY_ERROR;
-         goto error;
-       }
+        {
+          gnutls_assert ();
+          ret = GNUTLS_E_MEMORY_ERROR;
+          goto error;
+        }
     }
 
   for (i = 0; i < info->ncerts; i++)
     {
-      size = _gnutls_read_uint32 (&packed_session->data[pos]);
-      pos += sizeof (uint32_t);
-
-      ret =
-       _gnutls_set_datum (&info->raw_certificate_list[i],
-                          &packed_session->data[pos], size);
-      pos += size;
-
-      if (ret < 0)
-       {
-         gnutls_assert ();
-         goto error;
-       }
+      BUFFER_POP_DATUM(ps, &info->raw_certificate_list[i]);
     }
 
-
   return 0;
 
 error:
-  _gnutls_free_datum (&info->dh.prime);
-  _gnutls_free_datum (&info->dh.generator);
-  _gnutls_free_datum (&info->dh.public_key);
+  if (info)
+    {
+      _gnutls_free_datum (&info->dh.prime);
+      _gnutls_free_datum (&info->dh.generator);
+      _gnutls_free_datum (&info->dh.public_key);
 
-  _gnutls_free_datum (&info->rsa_export.modulus);
-  _gnutls_free_datum (&info->rsa_export.exponent);
+      _gnutls_free_datum (&info->rsa_export.modulus);
+      _gnutls_free_datum (&info->rsa_export.exponent);
 
-  for (j = 0; j < i; j++)
-    _gnutls_free_datum (&info->raw_certificate_list[j]);
+      for (j = 0; j < i; j++)
+        _gnutls_free_datum (&info->raw_certificate_list[j]);
 
-  gnutls_free (info->raw_certificate_list);
+      gnutls_free (info->raw_certificate_list);
+    }
 
   return ret;
 
@@ -501,37 +424,27 @@ error:
  *      x bytes the SRP username
  */
 static int
-pack_srp_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
+pack_srp_auth_info (gnutls_session_t session, gnutls_buffer_st * ps)
 {
   srp_server_auth_info_t info = _gnutls_get_auth_info (session);
-  int pack_size;
+  int len, ret;
+  void* size_pos;
+  size_t cur_size;
 
   if (info && info->username)
-    pack_size = strlen (info->username) + 1;   /* include the terminating null 
*/
+    len = strlen (info->username) + 1; /* include the terminating null */
   else
-    pack_size = 0;
+    len = 0;
 
-  packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
+  size_pos = ps->data + ps->length;
 
-  /* calculate the size and allocate the data.
-   */
-  packed_session->data =
-    gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 +
-                  session->security_parameters.extensions.
-                  session_ticket_len);
+  BUFFER_APPEND_NUM(ps, 0);
+  cur_size = ps->length;
 
-  if (packed_session->data == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  packed_session->data[0] = GNUTLS_CRD_SRP;
-  _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
+  BUFFER_APPEND_PFX(ps, info->username, len);
 
-  if (pack_size > 0)
-    memcpy (&packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)],
-           info->username, pack_size + 1);
+  /* write the real size */
+  _gnutls_write_uint32(ps->length-cur_size, size_pos);
 
   return 0;
 }
@@ -539,30 +452,19 @@ pack_srp_auth_info (gnutls_session_t session, 
gnutls_datum_t * packed_session)
 
 static int
 unpack_srp_auth_info (gnutls_session_t session,
-                     const gnutls_datum_t * packed_session)
+                     gnutls_buffer_st * ps)
 {
   size_t username_size;
   int ret;
   srp_server_auth_info_t info;
 
-  if (packed_session->data[0] != GNUTLS_CRD_SRP)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  username_size =
-    _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
-
-  if (username_size == 0)
-    return 0;                  /* nothing to be done */
-
-  /* a simple check for integrity */
-  if (username_size + 4 + PACK_HEADER_SIZE > packed_session->size)
+  BUFFER_POP_NUM(ps, username_size);
+  if (username_size > sizeof(info->username)) 
     {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
+      gnutls_assert();
+      return GNUTLS_E_INTERNAL_ERROR;
     }
+      
 
   ret =
     _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
@@ -580,11 +482,12 @@ unpack_srp_auth_info (gnutls_session_t session,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
-  memcpy (info->username,
-         &packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)],
-         username_size);
+  BUFFER_POP(ps, info->username, username_size);
 
-  return 0;
+  ret = 0;
+  
+error:
+  return ret;
 }
 #endif
 
@@ -606,50 +509,27 @@ unpack_srp_auth_info (gnutls_session_t session,
  */
 static int
 pack_anon_auth_info (gnutls_session_t session,
-                    gnutls_datum_t * packed_session)
+                    gnutls_buffer_st * ps)
 {
+  int cur_size, ret;
   anon_auth_info_t info = _gnutls_get_auth_info (session);
-  int pos = 0;
-  size_t pack_size;
-
-  if (info)
-    pack_size = 2 + 4 * 3 + info->dh.prime.size +
-      info->dh.generator.size + info->dh.public_key.size;
-  else
-    pack_size = 0;
+  void* size_pos;
 
-  packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
+  size_pos = ps->data + ps->length;
 
-  /* calculate the size and allocate the data.
-   */
-  packed_session->data =
-    gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 +
-                  session->security_parameters.extensions.
-                  session_ticket_len);
+  BUFFER_APPEND_NUM(ps, 0);
+  cur_size = ps->length;
 
-  if (packed_session->data == NULL)
+  if (info)
     {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
+      BUFFER_APPEND_NUM( ps, info->dh.secret_bits);
+      BUFFER_APPEND_PFX( ps, info->dh.prime.data, info->dh.prime.size);
+      BUFFER_APPEND_PFX( ps, info->dh.generator.data, info->dh.generator.size);
+      BUFFER_APPEND_PFX( ps, info->dh.public_key.data, 
info->dh.public_key.size);
     }
 
-  packed_session->data[0] = GNUTLS_CRD_ANON;
-  _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
-  pos += 4 + PACK_HEADER_SIZE;
-
-  if (pack_size > 0)
-    {
-      _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
-      pos += 2;
-
-      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
-      pos += 4 + info->dh.prime.size;
-      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
-      pos += 4 + info->dh.generator.size;
-      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
-      pos += 4 + info->dh.public_key.size;
-
-    }
+  /* write the real size */
+  _gnutls_write_uint32(ps->length-cur_size, size_pos);
 
   return 0;
 }
@@ -657,33 +537,18 @@ pack_anon_auth_info (gnutls_session_t session,
 
 static int
 unpack_anon_auth_info (gnutls_session_t session,
-                      const gnutls_datum_t * packed_session)
+                       gnutls_buffer_st * ps)
 {
+  int ret;
   size_t pack_size;
-  int pos = 0, size, ret;
-  anon_auth_info_t info;
-
-  if (packed_session->data[0] != GNUTLS_CRD_ANON)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
-  pos += PACK_HEADER_SIZE + 4;
+  anon_auth_info_t info = NULL;
 
+  BUFFER_POP_NUM(ps, pack_size);
 
   if (pack_size == 0)
-    return 0;                  /* nothing to be done */
+    return 0;  /* nothing to be done */
 
-  /* a simple check for integrity */
-  if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  /* client and serer have the same auth_info here
+  /* client and server have the same auth_info here
    */
   ret =
     _gnutls_auth_info_set (session, GNUTLS_CRD_ANON,
@@ -701,48 +566,22 @@ unpack_anon_auth_info (gnutls_session_t session,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
-  info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]);
-  pos += 2;
+  BUFFER_POP_NUM(ps, info->dh.secret_bits);
 
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      goto error;
-    }
-  pos += size;
+  BUFFER_POP_DATUM(ps, &info->dh.prime);
+  BUFFER_POP_DATUM(ps, &info->dh.generator);
+  BUFFER_POP_DATUM(ps, &info->dh.public_key);
 
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret =
-    _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      goto error;
-    }
-  pos += size;
+  return 0;
 
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret =
-    _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
-                      size);
-  if (ret < 0)
+error:
+  if (info)
     {
-      gnutls_assert ();
-      goto error;
+      _gnutls_free_datum (&info->dh.prime);
+      _gnutls_free_datum (&info->dh.generator);
+      _gnutls_free_datum (&info->dh.public_key);
     }
-  pos += size;
-
-  return 0;
 
-error:
-  _gnutls_free_datum (&info->dh.prime);
-  _gnutls_free_datum (&info->dh.generator);
-  _gnutls_free_datum (&info->dh.public_key);
   return ret;
 }
 #endif /* ANON */
@@ -766,108 +605,53 @@ error:
  *      x bytes the public key
  */
 static int
-pack_psk_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
+pack_psk_auth_info (gnutls_session_t session, gnutls_buffer_st * ps)
 {
   psk_auth_info_t info;
-  int pack_size, username_size = 0, hint_size = 0, pos;
+  int username_len;
+  int hint_len, ret;
+  void* size_pos;
+  size_t cur_size;
 
   info = _gnutls_get_auth_info (session);
 
-  if (info)
-    {
-      username_size = strlen (info->username) + 1;     /* include the 
terminating null */
-      hint_size = strlen (info->hint) + 1;     /* include the terminating null 
*/
-
-      pack_size = 1 + 4 + 4 + username_size + 4 + hint_size +
-       +2 + 4 + info->dh.prime.size + 4 + info->dh.generator.size +
-       4 + info->dh.public_key.size;
-    }
+  if (info && info->username)
+    username_len = strlen (info->username) + 1;        /* include the 
terminating null */
   else
-    pack_size = 0;
+    username_len = 0;
 
-  packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);
-
-  /* calculate the size and allocate the data.
-   */
-  packed_session->data =
-    gnutls_malloc (packed_session->size + MAX_SEC_PARAMS + 2 +
-                  session->security_parameters.extensions.
-                  session_ticket_len);
-
-  if (packed_session->data == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  pos = 0;
-
-  packed_session->data[pos] = GNUTLS_CRD_PSK;
-  pos++;
-
-  _gnutls_write_uint32 (pack_size, &packed_session->data[pos]);
-  pos += 4;
-
-  if (pack_size > 0)
-    {
-      _gnutls_write_uint32 (username_size, &packed_session->data[pos]);
-      pos += 4;
-
-      memcpy (&packed_session->data[pos], info->username, username_size);
-      pos += username_size;
+  if (info && info->hint)
+    hint_len = strlen (info->hint) + 1;        /* include the terminating null 
*/
+  else
+    hint_len = 0;
 
-      _gnutls_write_uint32 (hint_size, &packed_session->data[pos]);
-      pos += 4;
+  size_pos = ps->data + ps->length;
 
-      memcpy (&packed_session->data[pos], info->hint, hint_size);
-      pos += hint_size;
+  BUFFER_APPEND_NUM(ps, 0);
+  cur_size = ps->length;
 
-      _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
-      pos += 2;
+  BUFFER_APPEND_PFX(ps, info->username, username_len);
+  BUFFER_APPEND_PFX(ps, info->hint, hint_len);
 
-      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
-      pos += 4 + info->dh.prime.size;
-      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
-      pos += 4 + info->dh.generator.size;
-      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
-      pos += 4 + info->dh.public_key.size;
-    }
+  BUFFER_APPEND_NUM( ps, info->dh.secret_bits);
+  BUFFER_APPEND_PFX( ps, info->dh.prime.data, info->dh.prime.size);
+  BUFFER_APPEND_PFX( ps, info->dh.generator.data, info->dh.generator.size);
+  BUFFER_APPEND_PFX( ps, info->dh.public_key.data, info->dh.public_key.size);
 
+  /* write the real size */
+  _gnutls_write_uint32(ps->length-cur_size, size_pos);
 
   return 0;
 }
 
 static int
 unpack_psk_auth_info (gnutls_session_t session,
-                     const gnutls_datum_t * packed_session)
+                     gnutls_buffer_st * ps)
 {
   size_t username_size, hint_size;
-  size_t pack_size;
-  int pos = 0, size, ret;
+  int ret;
   psk_auth_info_t info;
 
-  if (packed_session->data[0] != GNUTLS_CRD_PSK)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
-  pos += PACK_HEADER_SIZE + 4;
-
-
-  if (pack_size == 0)
-    return 0;                  /* nothing to be done */
-
-  /* a simple check for integrity */
-  if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  /* client and serer have the same auth_info here
-   */
   ret =
     _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
                           sizeof (psk_auth_info_st), 1);
@@ -884,60 +668,36 @@ unpack_psk_auth_info (gnutls_session_t session,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
-  username_size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-
-  memcpy (info->username, &packed_session->data[pos], username_size);
-  pos += username_size;
-
-  hint_size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-
-  memcpy (info->hint, &packed_session->data[pos], hint_size);
-  pos += hint_size;
-
-  info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]);
-  pos += 2;
-
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
-  if (ret < 0)
+  BUFFER_POP_NUM(ps, username_size);
+  if (username_size > sizeof(info->username)) 
     {
-      gnutls_assert ();
-      goto error;
+      gnutls_assert();
+      return GNUTLS_E_INTERNAL_ERROR;
     }
-  pos += size;
 
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret =
-    _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      goto error;
-    }
-  pos += size;
+  BUFFER_POP(ps, info->username, username_size);
 
-  size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-  ret =
-    _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
-                      size);
-  if (ret < 0)
+  BUFFER_POP_NUM(ps, hint_size);
+  if (hint_size > sizeof(info->hint)) 
     {
-      gnutls_assert ();
-      goto error;
+      gnutls_assert();
+      return GNUTLS_E_INTERNAL_ERROR;
     }
-  pos += size;
+  BUFFER_POP(ps, info->hint, hint_size);
 
-  return 0;
+  BUFFER_POP_NUM(ps, info->dh.secret_bits);
+
+  BUFFER_POP_DATUM(ps, &info->dh.prime);
+  BUFFER_POP_DATUM(ps, &info->dh.generator);
+  BUFFER_POP_DATUM(ps, &info->dh.public_key);
 
+  ret = 0;
+  
 error:
   _gnutls_free_datum (&info->dh.prime);
   _gnutls_free_datum (&info->dh.generator);
   _gnutls_free_datum (&info->dh.public_key);
+
   return ret;
 }
 #endif
@@ -975,217 +735,97 @@ error:
  *            -------------------
  *                MAX: 165 bytes
  *
- *      EXTENSIONS:
- *      2 bytes the record send size
- *      2 bytes the record recv size
- *
- *      1 byte the SRP username size
- *      x bytes the SRP username (MAX_SRP_USERNAME)
- *
- *      2 bytes the number of server name extensions (up to 
MAX_SERVER_NAME_EXTENSIONS)
- *      1 byte the first name type
- *      2 bytes the size of the first name 
- *      x bytes the first name (MAX_SERVER_NAME_SIZE)
- *       and so on...
- *      2 bytes the session ticket size
- *      x bytes the session ticket (MAX_SESSION_TICKET_SIZE)
- *
- *           --------------------
- *                MAX: 
7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)+MAX_SESSION_TICKET_SIZE
  */
 static int
 pack_security_parameters (gnutls_session_t session,
-                         gnutls_datum_t * packed_session)
+                         gnutls_buffer_st * ps)
 {
-  int pos = 0;
-  size_t len, init, i;
+
+  int ret;
+  void* size_pos;
+  size_t cur_size;
 
   /* move after the auth info stuff.
    */
-  init =
-    _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 +
-    PACK_HEADER_SIZE;
-
-  pos = init + 4;              /* make some space to write later the size */
-
-  packed_session->data[pos++] = session->security_parameters.entity;
-  packed_session->data[pos++] = session->security_parameters.kx_algorithm;
-  packed_session->data[pos++] =
-    session->security_parameters.read_bulk_cipher_algorithm;
-  packed_session->data[pos++] =
-    session->security_parameters.read_mac_algorithm;
-  packed_session->data[pos++] =
-    session->security_parameters.read_compression_algorithm;
-  packed_session->data[pos++] =
-    session->security_parameters.write_bulk_cipher_algorithm;
-  packed_session->data[pos++] =
-    session->security_parameters.write_mac_algorithm;
-  packed_session->data[pos++] =
-    session->security_parameters.write_compression_algorithm;
-  packed_session->data[pos++] =
-    session->security_parameters.current_cipher_suite.suite[0];
-  packed_session->data[pos++] =
-    session->security_parameters.current_cipher_suite.suite[1];
-
-  packed_session->data[pos++] = session->security_parameters.cert_type;
-  packed_session->data[pos++] = session->security_parameters.version;
-
-  memcpy (&packed_session->data[pos],
-         session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
-  pos += GNUTLS_MASTER_SIZE;
-
-  memcpy (&packed_session->data[pos],
-         session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);
-  pos += GNUTLS_RANDOM_SIZE;
-  memcpy (&packed_session->data[pos],
-         session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
-  pos += GNUTLS_RANDOM_SIZE;
-
-  packed_session->data[pos++] = session->security_parameters.session_id_size;
-  memcpy (&packed_session->data[pos], session->security_parameters.session_id,
-         session->security_parameters.session_id_size);
-  pos += session->security_parameters.session_id_size;
-
-  _gnutls_write_uint32 (session->security_parameters.timestamp,
-                       &packed_session->data[pos]);
-  pos += 4;
-
-  /* Extensions */
-  _gnutls_write_uint16 (session->security_parameters.max_record_send_size,
-                       &packed_session->data[pos]);
-  pos += 2;
-
-  _gnutls_write_uint16 (session->security_parameters.max_record_recv_size,
-                       &packed_session->data[pos]);
-  pos += 2;
-
-  /* SRP */
-  len =
-    strlen ((char *) session->security_parameters.extensions.srp_username);
-  packed_session->data[pos++] = len;
-  memcpy (&packed_session->data[pos],
-         session->security_parameters.extensions.srp_username, len);
-  pos += len;
-
-  _gnutls_write_uint16 (session->security_parameters.
-                       extensions.server_names_size,
-                       &packed_session->data[pos]);
-  pos += 2;
-
-  for (i = 0; i < session->security_parameters.extensions.server_names_size;
-       i++)
-    {
-      packed_session->data[pos++] =
-       session->security_parameters.extensions.server_names[i].type;
-      _gnutls_write_uint16 (session->security_parameters.
-                           extensions.server_names[i].name_length,
-                           &packed_session->data[pos]);
-      pos += 2;
-
-      memcpy (&packed_session->data[pos],
-             session->security_parameters.extensions.server_names[i].name,
-             session->security_parameters.extensions.
-             server_names[i].name_length);
-      pos +=
-       session->security_parameters.extensions.server_names[i].name_length;
-    }
+  size_pos = ps->data + ps->length;
+
+  BUFFER_APPEND_NUM(ps, 0);
+  cur_size = ps->length;
+
 
-  _gnutls_write_uint16 (session->security_parameters.
-                       extensions.session_ticket_len,
-                       &packed_session->data[pos]);
-  pos += 2;
-  memcpy (&packed_session->data[pos],
-         session->security_parameters.extensions.session_ticket,
-         session->security_parameters.extensions.session_ticket_len);
-  pos += session->security_parameters.extensions.session_ticket_len;
+  BUFFER_APPEND(ps, &session->security_parameters.entity, 1);
+  BUFFER_APPEND(ps, &session->security_parameters.kx_algorithm, 1);
+  BUFFER_APPEND(ps, &session->security_parameters.read_bulk_cipher_algorithm, 
1);
+  BUFFER_APPEND(ps, &session->security_parameters.read_mac_algorithm, 1);
+  BUFFER_APPEND(ps, &session->security_parameters.read_compression_algorithm, 
1);
+  BUFFER_APPEND(ps, &session->security_parameters.write_bulk_cipher_algorithm, 
1);
+  BUFFER_APPEND(ps, &session->security_parameters.write_mac_algorithm, 1);
+  BUFFER_APPEND(ps, &session->security_parameters.write_compression_algorithm, 
1);
+  BUFFER_APPEND(ps, 
&session->security_parameters.current_cipher_suite.suite[0], 1);
+  BUFFER_APPEND(ps, 
&session->security_parameters.current_cipher_suite.suite[1], 1);
+  BUFFER_APPEND(ps, &session->security_parameters.cert_type, 1);
+  BUFFER_APPEND(ps, &session->security_parameters.version, 1);
 
-  /* write the total size */
-  _gnutls_write_uint32 (pos - init - 4, &packed_session->data[init]);
-  packed_session->size += pos - init;
+  BUFFER_APPEND(ps, session->security_parameters.master_secret, 
GNUTLS_MASTER_SIZE);
+  BUFFER_APPEND(ps, session->security_parameters.client_random, 
GNUTLS_RANDOM_SIZE);
+  BUFFER_APPEND(ps, session->security_parameters.server_random, 
GNUTLS_RANDOM_SIZE);
+  BUFFER_APPEND_NUM(ps, session->security_parameters.session_id_size);
+  BUFFER_APPEND_NUM(ps, session->security_parameters.max_record_send_size);
+  BUFFER_APPEND_NUM(ps, session->security_parameters.max_record_recv_size);
+  BUFFER_APPEND(ps, session->security_parameters.session_id, 
session->security_parameters.session_id_size);
+
+  BUFFER_APPEND_NUM(ps, session->security_parameters.timestamp);
+
+  _gnutls_write_uint32(ps->length-cur_size, size_pos);
 
   return 0;
 }
 
-
 static int
 unpack_security_parameters (gnutls_session_t session,
-                           const gnutls_datum_t * packed_session)
+                           gnutls_buffer_st * ps)
 {
-  size_t pack_size, init, i;
-  int pos = 0, len;
+  size_t pack_size;
+  int ret;
   time_t timestamp = time (0);
 
-
-  /* skip the auth info stuff */
-  init =
-    _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 +
-    PACK_HEADER_SIZE;
-
-  pos = init;
-
-  pack_size = _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
-
+  BUFFER_POP_NUM(ps, pack_size);
 
   if (pack_size == 0)
     return GNUTLS_E_INVALID_REQUEST;
 
-  /* a simple check for integrity */
-  if (pack_size > MAX_SEC_PARAMS + 2 + MAX_SESSION_TICKET_SIZE)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
   memset (&session->internals.resumed_security_parameters, 0,
          sizeof (session->internals.resumed_security_parameters));
-  session->internals.resumed_security_parameters.entity =
-    packed_session->data[pos++];
-  session->internals.resumed_security_parameters.kx_algorithm =
-    packed_session->data[pos++];
-  session->internals.resumed_security_parameters.read_bulk_cipher_algorithm =
-    packed_session->data[pos++];
-  session->internals.resumed_security_parameters.read_mac_algorithm =
-    packed_session->data[pos++];
-  session->internals.resumed_security_parameters.read_compression_algorithm =
-    packed_session->data[pos++];
-  session->internals.resumed_security_parameters.write_bulk_cipher_algorithm =
-    packed_session->data[pos++];
-  session->internals.resumed_security_parameters.write_mac_algorithm =
-    packed_session->data[pos++];
-  session->internals.resumed_security_parameters.write_compression_algorithm =
-    packed_session->data[pos++];
-  session->internals.resumed_security_parameters.
-    current_cipher_suite.suite[0] = packed_session->data[pos++];
-  session->internals.resumed_security_parameters.
-    current_cipher_suite.suite[1] = packed_session->data[pos++];
-
-  session->internals.resumed_security_parameters.cert_type =
-    packed_session->data[pos++];
-  session->internals.resumed_security_parameters.version =
-    packed_session->data[pos++];
-
-  memcpy (session->internals.resumed_security_parameters.master_secret,
-         &packed_session->data[pos], GNUTLS_MASTER_SIZE);
-  pos += GNUTLS_MASTER_SIZE;
-
-  memcpy (session->internals.resumed_security_parameters.client_random,
-         &packed_session->data[pos], GNUTLS_RANDOM_SIZE);
-  pos += GNUTLS_RANDOM_SIZE;
-  memcpy (session->internals.resumed_security_parameters.server_random,
-         &packed_session->data[pos], GNUTLS_RANDOM_SIZE);
-  pos += GNUTLS_RANDOM_SIZE;
-
-  session->internals.resumed_security_parameters.session_id_size =
-    packed_session->data[pos++];
-  memcpy (session->internals.resumed_security_parameters.session_id,
-         &packed_session->data[pos],
+
+  BUFFER_POP(ps, &session->internals.resumed_security_parameters.entity, 1);
+  BUFFER_POP(ps, &session->internals.resumed_security_parameters.kx_algorithm, 
1);
+  BUFFER_POP(ps, 
&session->internals.resumed_security_parameters.read_bulk_cipher_algorithm, 1);
+  BUFFER_POP(ps, 
&session->internals.resumed_security_parameters.read_mac_algorithm, 1);
+  BUFFER_POP(ps, 
&session->internals.resumed_security_parameters.read_compression_algorithm, 1);
+  BUFFER_POP(ps, 
&session->internals.resumed_security_parameters.write_bulk_cipher_algorithm, 1);
+  BUFFER_POP(ps, 
&session->internals.resumed_security_parameters.write_mac_algorithm, 1);
+  BUFFER_POP(ps, 
&session->internals.resumed_security_parameters.write_compression_algorithm, 1);
+  BUFFER_POP(ps, 
&session->internals.resumed_security_parameters.current_cipher_suite.suite[0], 
1);
+  BUFFER_POP(ps, &session->internals.resumed_security_parameters.
+    current_cipher_suite.suite[1], 1);
+  BUFFER_POP(ps, &session->internals.resumed_security_parameters.cert_type, 1);
+  BUFFER_POP(ps, &session->internals.resumed_security_parameters.version, 1);
+
+  BUFFER_POP(ps, &session->internals.resumed_security_parameters.master_secret,
+         GNUTLS_MASTER_SIZE);
+
+  BUFFER_POP(ps, &session->internals.resumed_security_parameters.client_random,
+         GNUTLS_RANDOM_SIZE);
+  BUFFER_POP(ps, &session->internals.resumed_security_parameters.server_random,
+         GNUTLS_RANDOM_SIZE);
+  BUFFER_POP_NUM(ps, 
session->internals.resumed_security_parameters.session_id_size);
+
+  BUFFER_POP(ps, &session->internals.resumed_security_parameters.session_id,
          session->internals.resumed_security_parameters.session_id_size);
-  pos += session->internals.resumed_security_parameters.session_id_size;
 
-  session->internals.resumed_security_parameters.timestamp =
-    _gnutls_read_uint32 (&packed_session->data[pos]);
-  pos += 4;
+  BUFFER_POP_NUM(ps, session->internals.resumed_security_parameters.timestamp);
+  BUFFER_POP_NUM(ps, 
session->internals.resumed_security_parameters.max_record_send_size);
+  BUFFER_POP_NUM(ps, 
session->internals.resumed_security_parameters.max_record_recv_size);
 
   if (timestamp - session->internals.resumed_security_parameters.timestamp >
       session->internals.expire_time
@@ -1195,60 +835,8 @@ unpack_security_parameters (gnutls_session_t session,
       return GNUTLS_E_EXPIRED;
     }
 
-  /* Extensions */
-  session->internals.resumed_security_parameters.max_record_send_size =
-    _gnutls_read_uint16 (&packed_session->data[pos]);
-  pos += 2;
-
-  session->internals.resumed_security_parameters.max_record_recv_size =
-    _gnutls_read_uint16 (&packed_session->data[pos]);
-  pos += 2;
-
-
-  /* SRP */
-  len = packed_session->data[pos++];   /* srp username length */
-  memcpy (session->internals.resumed_security_parameters.
-         extensions.srp_username, &packed_session->data[pos], len);
-  session->internals.resumed_security_parameters.
-    extensions.srp_username[len] = 0;
-  pos += len;
-
-  session->internals.resumed_security_parameters.
-    extensions.server_names_size =
-    _gnutls_read_uint16 (&packed_session->data[pos]);
-  pos += 2;
-  for (i = 0;
-       i <
-       session->internals.resumed_security_parameters.
-       extensions.server_names_size; i++)
-    {
-      session->internals.resumed_security_parameters.
-       extensions.server_names[i].type = packed_session->data[pos++];
-      session->internals.resumed_security_parameters.
-       extensions.server_names[i].name_length =
-       _gnutls_read_uint16 (&packed_session->data[pos]);
-      pos += 2;
-
-      memcpy (session->internals.resumed_security_parameters.
-             extensions.server_names[i].name, &packed_session->data[pos],
-             session->internals.resumed_security_parameters.
-             extensions.server_names[i].name_length);
-      pos +=
-       session->internals.resumed_security_parameters.
-       extensions.server_names[i].name_length;
-    }
-
-  session->internals.resumed_security_parameters.
-    extensions.session_ticket_len =
-    _gnutls_read_uint16 (&packed_session->data[pos]);
-  pos += 2;
-  session->internals.resumed_security_parameters.extensions.session_ticket =
-    gnutls_malloc (session->internals.resumed_security_parameters.
-                  extensions.session_ticket_len);
-  memcpy (session->internals.resumed_security_parameters.
-         extensions.session_ticket, &packed_session->data[pos],
-         session->internals.resumed_security_parameters.
-         extensions.session_ticket_len);
+  ret = 0;
 
-  return 0;
+error:
+  return ret;
 }
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index eca8a64..b5769de 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -45,6 +45,7 @@
 #include <auth_psk.h>
 #include <gnutls_algorithms.h>
 #include <gnutls_rsa_export.h>
+#include <gnutls_extensions.h>
 
 /* These should really be static, but src/tests.c calls them.  Make
    them public functions?  */
@@ -216,7 +217,6 @@ _gnutls_handshake_internal_state_init (gnutls_session_t 
session)
   session->internals.extensions_sent_size = 0;
 
   /* by default no selected certificate */
-  session->internals.proposed_record_size = DEFAULT_MAX_RECORD_SIZE;
   session->internals.adv_version_major = 0;
   session->internals.adv_version_minor = 0;
   session->internals.v2_hello = 0;
@@ -225,7 +225,6 @@ _gnutls_handshake_internal_state_init (gnutls_session_t 
session)
   session->internals.adv_version_minor = 0;
   session->internals.adv_version_minor = 0;
   session->internals.direction = 0;
-  session->internals.safe_renegotiation_received = 0;
 
   /* use out of band data for the last
    * handshake messages received.
@@ -385,6 +384,7 @@ gnutls_deinit (gnutls_session_t session)
 
   _gnutls_handshake_internal_state_clear (session);
   _gnutls_handshake_io_buffer_clear (session);
+  _gnutls_ext_free_session_data (session);
 
   _gnutls_free_datum (&session->connection_state.read_mac_secret);
   _gnutls_free_datum (&session->connection_state.write_mac_secret);
@@ -439,19 +439,6 @@ gnutls_deinit (gnutls_session_t session)
       session->key = NULL;
     }
 
-  gnutls_free (session->internals.srp_username);
-
-  if (session->internals.srp_password)
-    {
-      memset (session->internals.srp_password, 0,
-             strlen (session->internals.srp_password));
-      gnutls_free (session->internals.srp_password);
-    }
-
-  gnutls_free (session->security_parameters.extensions.session_ticket);
-  gnutls_free (session->internals.resumed_security_parameters.
-              extensions.session_ticket);
-
   memset (session, 0, sizeof (struct gnutls_session_int));
   gnutls_free (session);
 }
diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c
index c5c8493..4975dde 100644
--- a/lib/gnutls_str.c
+++ b/lib/gnutls_str.c
@@ -93,36 +93,29 @@ _gnutls_mem_cpy (char *dest, size_t dest_tot_size, const 
char *src,
 }
 
 void
-_gnutls_string_init (gnutls_string * str,
-                    gnutls_alloc_function alloc_func,
-                    gnutls_realloc_function realloc_func,
-                    gnutls_free_function free_func)
+_gnutls_buffer_init (gnutls_buffer_st * str)
 {
   str->data = str->allocd = NULL;
   str->max_length = 0;
   str->length = 0;
-
-  str->alloc_func = alloc_func;
-  str->free_func = free_func;
-  str->realloc_func = realloc_func;
 }
 
 void
-_gnutls_string_clear (gnutls_string * str)
+_gnutls_buffer_clear (gnutls_buffer_st * str)
 {
   if (str == NULL || str->allocd == NULL)
     return;
-  str->free_func (str->allocd);
+  gnutls_free (str->allocd);
 
   str->data = str->allocd = NULL;
   str->max_length = 0;
   str->length = 0;
 }
 
-#define MIN_CHUNK 256
+#define MIN_CHUNK 1024
 
 int
-_gnutls_string_append_data (gnutls_string * dest, const void *data,
+_gnutls_buffer_append_data (gnutls_buffer_st * dest, const void *data,
                            size_t data_size)
 {
   size_t tot_len = data_size + dest->length;
@@ -149,7 +142,7 @@ _gnutls_string_append_data (gnutls_string * dest, const 
void *data,
       size_t new_len =
        MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
 
-      dest->allocd = dest->realloc_func (dest->allocd, new_len);
+      dest->allocd = gnutls_realloc (dest->allocd, new_len);
       if (dest->allocd == NULL)
        {
          gnutls_assert ();
@@ -170,7 +163,7 @@ _gnutls_string_append_data (gnutls_string * dest, const 
void *data,
 }
 
 int
-_gnutls_string_resize (gnutls_string * dest, size_t new_size)
+_gnutls_buffer_resize (gnutls_buffer_st * dest, size_t new_size)
 {
   if (dest->max_length >= new_size)
     {
@@ -190,7 +183,7 @@ _gnutls_string_resize (gnutls_string * dest, size_t 
new_size)
       size_t alloc_len =
        MAX (new_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
 
-      dest->allocd = dest->realloc_func (dest->allocd, alloc_len);
+      dest->allocd = gnutls_realloc (dest->allocd, alloc_len);
       if (dest->allocd == NULL)
        {
          gnutls_assert ();
@@ -208,9 +201,9 @@ _gnutls_string_resize (gnutls_string * dest, size_t 
new_size)
 }
 
 int
-_gnutls_string_append_str (gnutls_string * dest, const char *src)
+_gnutls_buffer_append_str (gnutls_buffer_st * dest, const char *src)
 {
-  return _gnutls_string_append_data (dest, src, strlen (src));
+  return _gnutls_buffer_append_data (dest, src, strlen (src));
 }
 
 /* returns data from a string in a constant buffer.
@@ -218,7 +211,7 @@ _gnutls_string_append_str (gnutls_string * dest, const char 
*src)
  * data are appended in the buffer.
  */
 void
-_gnutls_string_get_datum (gnutls_string * str, gnutls_datum_t * data,
+_gnutls_buffer_pop_datum (gnutls_buffer_st * str, gnutls_datum_t * data,
                          size_t req_size)
 {
 
@@ -247,14 +240,48 @@ _gnutls_string_get_datum (gnutls_string * str, 
gnutls_datum_t * data,
   return;
 }
 
+/* converts the buffer to a datum if possible. After this call the buffer
+ * is at an usable state and might not be used or deinitialized */
+int
+_gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data)
+{
+
+  if (str->length == 0)
+    {
+      data->data = NULL;
+      data->size = 0;
+      return 0;
+    }
+
+  if (str->allocd != str->data)
+    {
+      data->data = gnutls_malloc(str->length);
+      if (data->data == NULL)
+        {
+          gnutls_assert();
+          return GNUTLS_E_MEMORY_ERROR;
+        }
+      memcpy(data->data, str->data, str->length);
+      data->size = str->length;
+      _gnutls_buffer_clear(str);
+    }
+  else
+    {
+      data->data = str->data;
+      data->size = str->length;
+    }
+
+  return 0;
+}
+
 /* returns data from a string in a constant buffer.
  */
 void
-_gnutls_string_get_data (gnutls_string * str, void *data, size_t * req_size)
+_gnutls_buffer_pop_data (gnutls_buffer_st * str, void *data, size_t * req_size)
 {
   gnutls_datum_t tdata;
 
-  _gnutls_string_get_datum (str, &tdata, *req_size);
+  _gnutls_buffer_pop_datum (str, &tdata, *req_size);
 
   *req_size = tdata.size;
   memcpy (data, tdata.data, tdata.size);
@@ -263,7 +290,7 @@ _gnutls_string_get_data (gnutls_string * str, void *data, 
size_t * req_size)
 }
 
 int
-_gnutls_string_append_printf (gnutls_string * dest, const char *fmt, ...)
+_gnutls_buffer_append_printf (gnutls_buffer_st * dest, const char *fmt, ...)
 {
   va_list args;
   int len;
@@ -276,19 +303,19 @@ _gnutls_string_append_printf (gnutls_string * dest, const 
char *fmt, ...)
   if (len < 0 || !str)
     return -1;
 
-  len = _gnutls_string_append_str (dest, str);
+  len = _gnutls_buffer_append_str (dest, str);
 
   free (str);
 
   return len;
 }
 
-static int _gnutls_string_insert_data(gnutls_string * dest, int pos, const 
void* str, size_t str_size)
+static int _gnutls_buffer_insert_data(gnutls_buffer_st * dest, int pos, const 
void* str, size_t str_size)
 {
         size_t orig_length = dest->length;
         int ret;
 
-        ret = _gnutls_string_resize(dest, dest->length+str_size); /* resize to 
make space */
+        ret = _gnutls_buffer_resize(dest, dest->length+str_size); /* resize to 
make space */
         if (ret < 0)
                 return ret;
 
@@ -300,7 +327,7 @@ static int _gnutls_string_insert_data(gnutls_string * dest, 
int pos, const void*
         return 0;
 }
 
-static void _gnutls_string_delete_data(gnutls_string * dest, int pos, size_t 
str_size)
+static void _gnutls_buffer_delete_data(gnutls_buffer_st * dest, int pos, 
size_t str_size)
 {
         memmove(&dest->data[pos], &dest->data[pos+str_size], 
dest->length-pos-str_size);
 
@@ -310,7 +337,7 @@ static void _gnutls_string_delete_data(gnutls_string * 
dest, int pos, size_t str
 }
 
 
-int _gnutls_string_escape(gnutls_string * dest, const char *const 
invalid_chars)
+int _gnutls_buffer_escape(gnutls_buffer_st * dest, const char *const 
invalid_chars)
 {
         static const char *x = "0123456789ABCDEF";
         int rv = -1;
@@ -328,9 +355,9 @@ int _gnutls_string_escape(gnutls_string * dest, const char 
*const invalid_chars)
                         t[1] = x[(dest->data[pos] & 0xf0) >> 4];
                         t[2] = x[(dest->data[pos] & 0x0f) >> 0];
 
-                        _gnutls_string_delete_data(dest, pos, 1);
+                        _gnutls_buffer_delete_data(dest, pos, 1);
 
-                        if (_gnutls_string_insert_data(dest, pos, t, 3) < 0) {
+                        if (_gnutls_buffer_insert_data(dest, pos, t, 3) < 0) {
                                         rv = -1;
                                         goto cleanup;
                         }
@@ -346,7 +373,7 @@ int _gnutls_string_escape(gnutls_string * dest, const char 
*const invalid_chars)
         return rv;
 }
 
-int _gnutls_string_unescape(gnutls_string * dest)
+int _gnutls_buffer_unescape(gnutls_buffer_st * dest)
 {
         int rv = -1;
         int pos = 0;
@@ -364,8 +391,8 @@ int _gnutls_string_unescape(gnutls_string * dest)
 
                         sscanf(b, "%08x", &u);
                         x = u & 0xff;
-                        _gnutls_string_delete_data(dest, pos, 3);
-                        _gnutls_string_insert_data(dest, pos, &x, 1);
+                        _gnutls_buffer_delete_data(dest, pos, 3);
+                        _gnutls_buffer_insert_data(dest, pos, &x, 1);
                 }
                 pos++;
         }
@@ -516,3 +543,90 @@ _gnutls_hostname_compare (const char *certname,
 
   return 0;
 }
+
+int _gnutls_buffer_append_prefix (gnutls_buffer_st * buf, size_t data_size)
+{
+    opaque ss[4];
+    _gnutls_write_uint32(data_size, ss);
+    return _gnutls_buffer_append_data(buf, ss, 4);
+}
+
+/* Reads an uint32 number from the buffer. If check is non zero it will also 
check whether
+ * the number read, is less than the data in the buffer
+ */
+int _gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t *data_size, int 
check)
+{
+    size_t size;
+    
+    if (buf->length < 4) {
+       gnutls_assert();
+       return GNUTLS_E_PARSING_ERROR;
+    }
+    
+    size = _gnutls_read_uint32(buf->data);
+    if (check && size > buf->length-4) {
+       gnutls_assert();
+       return GNUTLS_E_PARSING_ERROR;
+    }
+    
+    buf->data+=4;
+    buf->length-=4;
+    
+    *data_size = size;
+    
+    return 0;
+}
+
+int _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st * buf, gnutls_datum_t* 
data)
+{
+    size_t size;
+    int ret;
+    
+    ret = _gnutls_buffer_pop_prefix(buf, &size, 1);
+    if (ret < 0) {
+       gnutls_assert();
+       return ret;
+    }
+
+    if (size > 0) {
+       size_t osize = size;
+       _gnutls_buffer_pop_datum(buf, data, size);
+       if (osize != data->size) {
+           gnutls_assert();
+           return GNUTLS_E_PARSING_ERROR;
+       }
+    } else {
+       data->size = 0;
+       data->data = NULL;
+    }
+    
+    return 0;
+}
+
+int _gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, const void 
*data,
+                               size_t data_size)
+{
+    _gnutls_buffer_append_prefix(buf, data_size);
+    if (data_size > 0)
+      return _gnutls_buffer_append_data(buf, data, data_size);
+    
+    return 0;
+}
+
+int _gnutls_buffer_pop_data_prefix (gnutls_buffer_st * buf, void * data, 
size_t * data_size)
+{
+    size_t size;
+    int ret;
+    
+    ret = _gnutls_buffer_pop_prefix(buf, &size, 1);
+    if (ret < 0) {
+       gnutls_assert();
+       return ret;
+    }
+
+    if (size > 0)
+       _gnutls_buffer_pop_data(buf, data, data_size);
+    
+    return 0;
+}
+
diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h
index a011f4a..7d7df47 100644
--- a/lib/gnutls_str.h
+++ b/lib/gnutls_str.h
@@ -27,6 +27,7 @@
 # define GNUTLS_STR_H
 
 #include <gnutls_int.h>
+#include <gnutls_datum.h>
 
 void _gnutls_str_cpy (char *dest, size_t dest_tot_size, const char *src);
 void _gnutls_mem_cpy (char *dest, size_t dest_tot_size, const char *src,
@@ -39,26 +40,35 @@ typedef struct
   opaque *data;                        /* API: pointer to data to copy from */
   size_t max_length;
   size_t length;               /* API: current length */
-  gnutls_realloc_function realloc_func;
-  gnutls_alloc_function alloc_func;
-  gnutls_free_function free_func;
-} gnutls_string;
-
-void _gnutls_string_init (gnutls_string *, gnutls_alloc_function,
-                         gnutls_realloc_function, gnutls_free_function);
-void _gnutls_string_clear (gnutls_string *);
-int _gnutls_string_resize (gnutls_string *, size_t new_size);
-
-int _gnutls_string_append_str (gnutls_string *, const char *str);
-int _gnutls_string_append_data (gnutls_string *, const void *data,
+} gnutls_buffer_st;
+
+void _gnutls_buffer_init (gnutls_buffer_st *);
+void _gnutls_buffer_clear (gnutls_buffer_st *);
+int _gnutls_buffer_resize (gnutls_buffer_st *, size_t new_size);
+
+int _gnutls_buffer_append_str (gnutls_buffer_st *, const char *str);
+int _gnutls_buffer_append_data (gnutls_buffer_st *, const void *data,
                                size_t data_size);
 
-void _gnutls_string_get_data (gnutls_string *, void *, size_t * size);
-void _gnutls_string_get_datum (gnutls_string *, gnutls_datum_t *,
+#include <gnutls_num.h>
+
+int _gnutls_buffer_append_prefix (gnutls_buffer_st * buf, size_t data_size);
+
+int _gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, 
+    const void *data, size_t data_size);
+void _gnutls_buffer_pop_data (gnutls_buffer_st *, void *, size_t * size);
+void _gnutls_buffer_pop_datum (gnutls_buffer_st *, gnutls_datum_t *,
                               size_t max_size);
 
-int _gnutls_string_escape(gnutls_string * dest, const char *const 
invalid_chars);
-int _gnutls_string_unescape(gnutls_string * dest);
+int _gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t *data_size, int 
check);
+
+int _gnutls_buffer_pop_data_prefix (gnutls_buffer_st * buf, void * data, 
size_t * data_size);
+
+int _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st * buf, gnutls_datum_t* 
data);
+int _gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data);
+
+int _gnutls_buffer_escape(gnutls_buffer_st * dest, const char *const 
invalid_chars);
+int _gnutls_buffer_unescape(gnutls_buffer_st * dest);
 
 #ifndef __attribute__
 /* This feature is available in gcc versions 2.5 and later.  */
@@ -67,18 +77,9 @@ int _gnutls_string_unescape(gnutls_string * dest);
 # endif
 #endif
 
-int _gnutls_string_append_printf (gnutls_string * dest, const char *fmt, ...)
+int _gnutls_buffer_append_printf (gnutls_buffer_st * dest, const char *fmt, 
...)
   __attribute__ ((format (printf, 2, 3)));
 
-typedef gnutls_string gnutls_buffer;
-
-#define _gnutls_buffer_init(buf) _gnutls_string_init(buf, gnutls_malloc, 
gnutls_realloc, gnutls_free);
-#define _gnutls_buffer_clear _gnutls_string_clear
-#define _gnutls_buffer_append _gnutls_string_append_data
-#define _gnutls_buffer_get_datum _gnutls_string_get_datum
-#define _gnutls_buffer_get_data _gnutls_string_get_data
-#define _gnutls_buffer_resize _gnutls_string_resize
-
 char *_gnutls_bin2hex (const void *old, size_t oldlen, char *buffer,
                       size_t buffer_size, const char* separator);
 int _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data,
@@ -88,4 +89,60 @@ int _gnutls_hostname_compare (const char *certname, size_t 
certnamesize,
                              const char *hostname);
 #define MAX_CN 256
 
+#define BUFFER_APPEND(b, x, s) { \
+        ret = _gnutls_buffer_append_data(b, x, s); \
+        if (ret < 0) { \
+            gnutls_assert(); \
+            return ret; \
+        } \
+    }
+
+#define BUFFER_APPEND_PFX(b, x, s) { \
+        ret = _gnutls_buffer_append_data_prefix(b, x, s); \
+        if (ret < 0) { \
+            gnutls_assert(); \
+            return ret; \
+        } \
+    }
+
+#define BUFFER_APPEND_NUM(b, s) { \
+        ret = _gnutls_buffer_append_prefix(b, s); \
+        if (ret < 0) { \
+            gnutls_assert(); \
+            return ret; \
+        } \
+    }
+
+
+#define BUFFER_POP(b, x, s) { \
+        size_t is = s; \
+        _gnutls_buffer_pop_data(b, x, &is); \
+        if (is != s) { \
+            ret = GNUTLS_E_PARSING_ERROR; \
+            gnutls_assert(); \
+            goto error; \
+        } \
+    }
+
+#define BUFFER_POP_DATUM(b, o) { \
+        gnutls_datum_t d; \
+        ret = _gnutls_buffer_pop_datum_prefix(b, &d); \
+        if (ret >= 0) \
+            ret = _gnutls_set_datum (o, d.data, d.size); \
+        if (ret < 0) { \
+            gnutls_assert(); \
+            goto error; \
+        } \
+    }
+
+#define BUFFER_POP_NUM(b, o) { \
+        size_t s; \
+        ret = _gnutls_buffer_pop_prefix(b, &s, 0); \
+        if (ret < 0) { \
+            gnutls_assert(); \
+            goto error; \
+        } \
+        o = s; \
+    }
+
 #endif
diff --git a/lib/gnutls_supplemental.c b/lib/gnutls_supplemental.c
index 46debd3..b2a1dca 100644
--- a/lib/gnutls_supplemental.c
+++ b/lib/gnutls_supplemental.c
@@ -52,7 +52,7 @@
 
 typedef int (*supp_recv_func) (gnutls_session_t session,
                               const opaque * data, size_t data_size);
-typedef int (*supp_send_func) (gnutls_session_t session, gnutls_buffer * buf);
+typedef int (*supp_send_func) (gnutls_session_t session, gnutls_buffer_st * 
buf);
 
 typedef struct
 {
@@ -101,13 +101,13 @@ get_supp_func_recv 
(gnutls_supplemental_data_format_type_t type)
 }
 
 int
-_gnutls_gen_supplemental (gnutls_session_t session, gnutls_buffer * buf)
+_gnutls_gen_supplemental (gnutls_session_t session, gnutls_buffer_st * buf)
 {
   gnutls_supplemental_entry *p;
   int ret;
 
   /* Make room for 3 byte length field. */
-  ret = _gnutls_buffer_append (buf, "\0\0\0", 3);
+  ret = _gnutls_buffer_append_data (buf, "\0\0\0", 3);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -120,7 +120,7 @@ _gnutls_gen_supplemental (gnutls_session_t session, 
gnutls_buffer * buf)
       size_t sizepos = buf->length;
 
       /* Make room for supplement type and length byte length field. */
-      ret = _gnutls_buffer_append (buf, "\0\0\0\0", 4);
+      ret = _gnutls_buffer_append_data (buf, "\0\0\0\0", 4);
       if (ret < 0)
        {
          gnutls_assert ();
diff --git a/lib/gnutls_supplemental.h b/lib/gnutls_supplemental.h
index 20ad617..bf21c25 100644
--- a/lib/gnutls_supplemental.h
+++ b/lib/gnutls_supplemental.h
@@ -26,4 +26,4 @@
 
 int _gnutls_parse_supplemental (gnutls_session_t session,
                                const uint8_t * data, int data_size);
-int _gnutls_gen_supplemental (gnutls_session_t session, gnutls_buffer * buf);
+int _gnutls_gen_supplemental (gnutls_session_t session, gnutls_buffer_st * 
buf);
diff --git a/lib/includes/gnutls/compat.h b/lib/includes/gnutls/compat.h
index 5cae317..566f8c5 100644
--- a/lib/includes/gnutls/compat.h
+++ b/lib/includes/gnutls/compat.h
@@ -165,4 +165,10 @@ void gnutls_certificate_server_set_retrieve_function
     gnutls_sign_func
     gnutls_sign_callback_get (gnutls_session_t session, void **userdata);
 
+  int gnutls_ext_register (int type,
+                          const char *name,
+                          gnutls_ext_parse_type_t parse_type,
+                          gnutls_ext_recv_func recv_func,
+                          gnutls_ext_send_func send_func) 
_GNUTLS_GCC_ATTR_DEPRECATED;
+
 #endif /* _GNUTLS_COMPAT_H */
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 441b428..7ea6ea3 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -817,11 +817,6 @@ extern "C"
     GNUTLS_EXT_NONE = 4,
   } gnutls_ext_parse_type_t;
 
-  int gnutls_ext_register (int type,
-                          const char *name,
-                          gnutls_ext_parse_type_t parse_type,
-                          gnutls_ext_recv_func recv_func,
-                          gnutls_ext_send_func send_func);
 
   /**
    * gnutls_server_name_type_t:
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 527c618..cc93d6c 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -706,6 +706,13 @@ GNUTLS_PRIVATE {
     _gnutls_hash_init;
     _gnutls_hash_deinit;
     _gnutls_hash;
+    _gnutls_ext_get_session_data;
+    _gnutls_ext_set_session_data;
+    _gnutls_ext_register;
+    _gnutls_buffer_append_prefix;
+    _gnutls_buffer_append_data_prefix;
+    _gnutls_buffer_pop_data;
+    _gnutls_buffer_pop_prefix;
 
     # Internal symbols needed by psktool:
 
diff --git a/lib/openpgp/output.c b/lib/openpgp/output.c
index 20d2855..0413668 100644
--- a/lib/openpgp/output.c
+++ b/lib/openpgp/output.c
@@ -33,11 +33,11 @@
 #include "gettext.h"
 #define _(String) dgettext (PACKAGE, String)
 
-#define addf _gnutls_string_append_printf
-#define adds _gnutls_string_append_str
+#define addf _gnutls_buffer_append_printf
+#define adds _gnutls_buffer_append_str
 
 static void
-hexdump (gnutls_string * str, const char *data, size_t len, const char *spc)
+hexdump (gnutls_buffer_st * str, const char *data, size_t len, const char *spc)
 {
   size_t j;
 
@@ -61,7 +61,7 @@ hexdump (gnutls_string * str, const char *data, size_t len, 
const char *spc)
 }
 
 static void
-hexprint (gnutls_string * str, const char *data, size_t len)
+hexprint (gnutls_buffer_st * str, const char *data, size_t len)
 {
   size_t j;
 
@@ -75,7 +75,7 @@ hexprint (gnutls_string * str, const char *data, size_t len)
 }
 
 static void
-print_key_usage (gnutls_string * str, gnutls_openpgp_crt_t cert,
+print_key_usage (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert,
                 unsigned int idx)
 {
   unsigned int key_usage;
@@ -110,7 +110,7 @@ print_key_usage (gnutls_string * str, gnutls_openpgp_crt_t 
cert,
  * otherwise the subkey.
  */
 static void
-print_key_id (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
+print_key_id (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert, int idx)
 {
   gnutls_openpgp_keyid_t id;
   int err;
@@ -134,7 +134,7 @@ print_key_id (gnutls_string * str, gnutls_openpgp_crt_t 
cert, int idx)
  * otherwise the subkey.
  */
 static void
-print_key_fingerprint (gnutls_string * str, gnutls_openpgp_crt_t cert)
+print_key_fingerprint (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert)
 {
   char fpr[128];
   size_t fpr_size = sizeof (fpr);
@@ -152,7 +152,7 @@ print_key_fingerprint (gnutls_string * str, 
gnutls_openpgp_crt_t cert)
 }
 
 static void
-print_key_revoked (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
+print_key_revoked (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert, int idx)
 {
   int err;
 
@@ -168,7 +168,7 @@ print_key_revoked (gnutls_string * str, 
gnutls_openpgp_crt_t cert, int idx)
 }
 
 static void
-print_key_times (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
+print_key_times (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert, int idx)
 {
   time_t tim;
 
@@ -218,7 +218,7 @@ print_key_times (gnutls_string * str, gnutls_openpgp_crt_t 
cert, int idx)
 }
 
 static void
-print_key_info (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
+print_key_info (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert, int idx)
 {
   int err;
   unsigned int bits;
@@ -307,7 +307,7 @@ print_key_info (gnutls_string * str, gnutls_openpgp_crt_t 
cert, int idx)
 }
 
 static void
-print_cert (gnutls_string * str, gnutls_openpgp_crt_t cert)
+print_cert (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert)
 {
   int i, subkeys;
   int err;
@@ -388,7 +388,7 @@ print_cert (gnutls_string * str, gnutls_openpgp_crt_t cert)
 }
 
 static void
-print_oneline (gnutls_string * str, gnutls_openpgp_crt_t cert)
+print_oneline (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert)
 {
   int err, i;
 
@@ -514,20 +514,20 @@ gnutls_openpgp_crt_print (gnutls_openpgp_crt_t cert,
                          gnutls_certificate_print_formats_t format,
                          gnutls_datum_t * out)
 {
-  gnutls_string str;
+  gnutls_buffer_st str;
 
-  _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free);
+  _gnutls_buffer_init (&str);
 
   if (format == GNUTLS_CRT_PRINT_ONELINE)
     print_oneline (&str, cert);
   else
     {
-      _gnutls_string_append_str (&str,
+      _gnutls_buffer_append_str (&str,
                                 _("OpenPGP Certificate Information:\n"));
       print_cert (&str, cert);
     }
 
-  _gnutls_string_append_data (&str, "\0", 1);
+  _gnutls_buffer_append_data (&str, "\0", 1);
 
   out->data = str.data;
   out->size = strlen (str.data);
diff --git a/lib/pakchois/pakchois.c b/lib/pakchois/pakchois.c
index 6d06f4a..5ecbe36 100644
--- a/lib/pakchois/pakchois.c
+++ b/lib/pakchois/pakchois.c
@@ -62,6 +62,7 @@ struct provider {
     const struct ck_function_list *fns;
     unsigned int refcount;
     struct provider *next, **prevref;
+    void* reserved;
 };
 
 struct pakchois_module_s {
@@ -297,6 +298,7 @@ ck_rv_t rv;
     prov->handle = h;
     prov->fns = fns;
     prov->refcount = 1;
+    prov->reserved = reserved;
 
     /* Require OS locking, the only sane option. */
     memset(&args, 0, sizeof args);
@@ -375,15 +377,45 @@ fail_locked:
     return rv;
 }    
 
+static void providers_reinit(void)
+{
+    struct ck_c_initialize_args args;
+    ck_rv_t rv;
+    struct provider * p;
+
+    assert(pthread_mutex_lock(&provider_mutex) == 0);
+
+    memset(&args, 0, sizeof args);
+    args.flags = CKF_OS_LOCKING_OK;
+
+    for (p = provider_list; p; p = p->next) {
+        args.reserved = p->reserved;
+        rv = p->fns->C_Initialize(&args);
+        assert(rv == CKR_OK); /* what can we do? */
+    }
+
+    pthread_mutex_unlock(&provider_mutex);
+}
+
 static ck_rv_t load_module(pakchois_module_t **module, const char *name, 
                            void *reserved, unsigned int real_name)
 {
     ck_rv_t rv;
     pakchois_module_t *pm = malloc(sizeof *pm);
+    static int forkinit = 0;
 
     if (!pm) {
         return CKR_HOST_MEMORY;
     }
+    
+    assert(pthread_mutex_lock(&provider_mutex) == 0);
+
+    if (forkinit == 0) {
+       pthread_atfork(NULL, NULL, providers_reinit);
+       forkinit++;
+    }
+
+    pthread_mutex_unlock(&provider_mutex);
 
     rv = load_provider(&pm->provider, name, reserved, real_name);
     if (rv) {
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
index f8bf51a..f2b3708 100644
--- a/lib/pkcs11.c
+++ b/lib/pkcs11.c
@@ -343,12 +343,12 @@ void 
gnutls_pkcs11_set_token_function(gnutls_pkcs11_token_callback_t fn,
 
 static int unescape_string (char* output, const char* input, size_t* size, 
char terminator)
 {
-    gnutls_string str;
+    gnutls_buffer_st str;
     int ret = 0;
     char* p;
     int len;
     
-    _gnutls_string_init(&str, gnutls_malloc, gnutls_realloc, gnutls_free);
+    _gnutls_buffer_init(&str);
     
     /* find terminator */
     p = strchr(input, terminator);
@@ -357,27 +357,27 @@ static int unescape_string (char* output, const char* 
input, size_t* size, char
     else
         len = strlen(input);
 
-    ret = _gnutls_string_append_data(&str, input, len);
+    ret = _gnutls_buffer_append_data(&str, input, len);
     if (ret < 0) {
         gnutls_assert();
         return ret;
     }
 
-    ret = _gnutls_string_unescape(&str);
+    ret = _gnutls_buffer_unescape(&str);
     if (ret < 0) {
         gnutls_assert();
         return ret;
     }
 
-    ret = _gnutls_string_append_data(&str, "", 1);
+    ret = _gnutls_buffer_append_data(&str, "", 1);
     if (ret < 0) {
         gnutls_assert();
         return ret;
     }
 
-    _gnutls_string_get_data(&str, output, size);
+    _gnutls_buffer_pop_data(&str, output, size);
 
-    _gnutls_string_clear(&str);
+    _gnutls_buffer_clear(&str);
 
     return ret;
 }
@@ -493,29 +493,29 @@ cleanup:
 
 #define INVALID_CHARS       "\\/\"'%&address@hidden <>{}[]()`|:;,.+-"
 
-static int append(gnutls_string* dest, const char* tname, const char* p11name, 
int init)
+static int append(gnutls_buffer_st* dest, const char* tname, const char* 
p11name, int init)
 {
-        gnutls_string tmpstr;
+        gnutls_buffer_st tmpstr;
         int ret;
 
-        _gnutls_string_init(&tmpstr, gnutls_malloc, gnutls_realloc, 
gnutls_free);
-        if ((ret=_gnutls_string_append_str(&tmpstr, tname))<0) {
+        _gnutls_buffer_init(&tmpstr);
+        if ((ret=_gnutls_buffer_append_str(&tmpstr, tname))<0) {
                 gnutls_assert();
                 goto cleanup;
         }
 
-        ret = _gnutls_string_escape(&tmpstr, INVALID_CHARS);
+        ret = _gnutls_buffer_escape(&tmpstr, INVALID_CHARS);
         if (ret < 0) {
                 gnutls_assert();
                 goto cleanup;
         }
 
-        if ((ret=_gnutls_string_append_data(&tmpstr, "", 1)) < 0) {
+        if ((ret=_gnutls_buffer_append_data(&tmpstr, "", 1)) < 0) {
                 gnutls_assert();
                 goto cleanup;
         }
 
-        if ((ret=_gnutls_string_append_printf(dest, "%s%s=%s", 
(init!=0)?";":"", p11name, tmpstr.data)) < 0) {
+        if ((ret=_gnutls_buffer_append_printf(dest, "%s%s=%s", 
(init!=0)?";":"", p11name, tmpstr.data)) < 0) {
                 gnutls_assert();
                 goto cleanup;
         }
@@ -523,7 +523,7 @@ static int append(gnutls_string* dest, const char* tname, 
const char* p11name, i
         ret = 0;
 
 cleanup:
-        _gnutls_string_clear(&tmpstr);
+        _gnutls_buffer_clear(&tmpstr);
 
         return ret;
 
@@ -532,13 +532,13 @@ cleanup:
 
 int pkcs11_info_to_url(const struct pkcs11_url_info* info, char** url)
 {
-    gnutls_string str;
+    gnutls_buffer_st str;
     int init = 0;
     int ret;
     
-    _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free);
+    _gnutls_buffer_init (&str);
 
-    _gnutls_string_append_str(&str, "pkcs11:");
+    _gnutls_buffer_append_str(&str, "pkcs11:");
 
     if (info->token[0]) {
         ret = append(&str, info->token, "token", init);
@@ -596,21 +596,21 @@ int pkcs11_info_to_url(const struct pkcs11_url_info* 
info, char** url)
     }
 
     if (info->id[0] != 0) {
-        ret = _gnutls_string_append_printf(&str, ";id=%s", info->id);
+        ret = _gnutls_buffer_append_printf(&str, ";id=%s", info->id);
         if (ret < 0) {
             gnutls_assert();
             return ret;
         }
     }
     
-    _gnutls_string_append_data(&str, "", 1);
+    _gnutls_buffer_append_data(&str, "", 1);
 
     *url = str.data;
     
     return 0;
 
 cleanup:
-    _gnutls_string_clear(&str);
+    _gnutls_buffer_clear(&str);
     return ret;
 }
 
@@ -1474,7 +1474,7 @@ gnutls_pkcs11_obj_type_t gnutls_pkcs11_obj_get_type 
(gnutls_pkcs11_obj_t obj)
 }
 
 struct pkey_list {
-    gnutls_string *key_ids;
+    gnutls_buffer_st *key_ids;
     size_t key_ids_size;
 };
 
@@ -1599,7 +1599,7 @@ static int find_privkeys(pakchois_session_t *pks, struct 
token_info* info, struc
         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     }
 
-    list->key_ids = gnutls_malloc(sizeof(gnutls_string)*list->key_ids_size);
+    list->key_ids = gnutls_malloc(sizeof(gnutls_buffer_st)*list->key_ids_size);
     if (list->key_ids == NULL) {
         gnutls_assert();
         return GNUTLS_E_MEMORY_ERROR;
@@ -1624,10 +1624,10 @@ static int find_privkeys(pakchois_session_t *pks, 
struct token_info* info, struc
         a[0].value = certid_tmp;
         a[0].value_len = sizeof(certid_tmp);
 
-        _gnutls_string_init(&list->key_ids[current], gnutls_malloc, 
gnutls_realloc, gnutls_free);
+        _gnutls_buffer_init(&list->key_ids[current]);
 
         if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) {
-            _gnutls_string_append_data(&list->key_ids[current], a[0].value, 
a[0].value_len);
+            _gnutls_buffer_append_data(&list->key_ids[current], a[0].value, 
a[0].value_len);
             current++;
         }
 
@@ -1889,7 +1889,7 @@ fail:
     pakchois_find_objects_final(pks);
     if (plist.key_ids != NULL) {
         for (i=0;i<plist.key_ids_size;i++) {
-            _gnutls_string_clear(&plist.key_ids[i]);
+            _gnutls_buffer_clear(&plist.key_ids[i]);
         }
         gnutls_free( plist.key_ids);
     }
diff --git a/lib/x509/dn.c b/lib/x509/dn.c
index d9e1592..4288470 100644
--- a/lib/x509/dn.c
+++ b/lib/x509/dn.c
@@ -91,7 +91,7 @@ _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct,
                       const char *asn1_rdn_name, char *buf,
                       size_t * sizeof_buf)
 {
-  gnutls_string out_str;
+  gnutls_buffer_st out_str;
   int k2, k1, result;
   char tmpbuffer1[ASN1_MAX_NAME_SIZE];
   char tmpbuffer2[ASN1_MAX_NAME_SIZE];
@@ -115,7 +115,7 @@ _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct,
   else
     *sizeof_buf = 0;
 
-  _gnutls_string_init (&out_str, gnutls_malloc, gnutls_realloc, gnutls_free);
+  _gnutls_buffer_init (&out_str);
 
   k1 = 0;
   do
@@ -214,7 +214,7 @@ _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct,
              result = _gnutls_asn2err (result);
              goto cleanup;
            }
-#define STR_APPEND(y) if ((result=_gnutls_string_append_str( &out_str, y)) < 
0) { \
+#define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 
0) { \
        gnutls_assert(); \
        goto cleanup; \
 }
@@ -309,7 +309,7 @@ _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct,
 
   if (buf)
     {
-      _gnutls_string_get_data (&out_str, buf, sizeof_buf);
+      _gnutls_buffer_pop_data (&out_str, buf, sizeof_buf);
       buf[*sizeof_buf] = 0;
     }
   else
@@ -321,7 +321,7 @@ cleanup:
   gnutls_free (value2);
   gnutls_free (string);
   gnutls_free (escaped);
-  _gnutls_string_clear (&out_str);
+  _gnutls_buffer_clear (&out_str);
   return result;
 }
 
diff --git a/lib/x509/output.c b/lib/x509/output.c
index 126b88c..e3000c0 100644
--- a/lib/x509/output.c
+++ b/lib/x509/output.c
@@ -37,13 +37,13 @@
 #include "gettext.h"
 #define _(String) dgettext (PACKAGE, String)
 
-#define addf _gnutls_string_append_printf
-#define adds _gnutls_string_append_str
+#define addf _gnutls_buffer_append_printf
+#define adds _gnutls_buffer_append_str
 
 #define ERROR_STR (char*) "(error)"
 
 static void
-hexdump (gnutls_string * str, const char *data, size_t len, const char *spc)
+hexdump (gnutls_buffer_st * str, const char *data, size_t len, const char *spc)
 {
   size_t j;
 
@@ -67,7 +67,7 @@ hexdump (gnutls_string * str, const char *data, size_t len, 
const char *spc)
 }
 
 static void
-hexprint (gnutls_string * str, const char *data, size_t len)
+hexprint (gnutls_buffer_st * str, const char *data, size_t len)
 {
   size_t j;
 
@@ -82,7 +82,7 @@ hexprint (gnutls_string * str, const char *data, size_t len)
 
 
 static void
-asciiprint (gnutls_string * str, const char *data, size_t len)
+asciiprint (gnutls_buffer_st * str, const char *data, size_t len)
 {
   size_t j;
 
@@ -135,7 +135,7 @@ ip_to_string (void *_ip, int ip_size, char *string, int 
string_size)
 }
 
 static void
-print_proxy (gnutls_string * str, gnutls_x509_crt_t cert)
+print_proxy (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
 {
   int pathlen;
   char *policyLanguage;
@@ -172,7 +172,7 @@ print_proxy (gnutls_string * str, gnutls_x509_crt_t cert)
 }
 
 static void
-print_ski (gnutls_string * str, gnutls_x509_crt_t cert)
+print_ski (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
 {
   char *buffer = NULL;
   size_t size = 0;
@@ -224,7 +224,7 @@ typedef union
 } cert_type_t;
 
 static void
-print_aki (gnutls_string * str, int type, cert_type_t cert)
+print_aki (gnutls_buffer_st * str, int type, cert_type_t cert)
 {
   char *buffer = NULL;
   size_t size = 0;
@@ -278,7 +278,7 @@ print_aki (gnutls_string * str, int type, cert_type_t cert)
 }
 
 static void
-print_key_usage (gnutls_string * str, const char *prefix, int type,
+print_key_usage (gnutls_buffer_st * str, const char *prefix, int type,
                 cert_type_t cert)
 {
   unsigned int key_usage;
@@ -320,7 +320,7 @@ print_key_usage (gnutls_string * str, const char *prefix, 
int type,
 #ifdef ENABLE_PKI
 
 static void
-print_crldist (gnutls_string * str, gnutls_x509_crt_t cert)
+print_crldist (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
 {
   char *buffer = NULL;
   size_t size;
@@ -405,7 +405,7 @@ print_crldist (gnutls_string * str, gnutls_x509_crt_t cert)
 }
 
 static void
-print_key_purpose (gnutls_string * str, const char *prefix, int type,
+print_key_purpose (gnutls_buffer_st * str, const char *prefix, int type,
                   cert_type_t cert)
 {
   int indx;
@@ -481,7 +481,7 @@ print_key_purpose (gnutls_string * str, const char *prefix, 
int type,
 #endif
 
 static void
-print_basic (gnutls_string * str, const char *prefix, int type,
+print_basic (gnutls_buffer_st * str, const char *prefix, int type,
             cert_type_t cert)
 {
   int pathlen;
@@ -513,7 +513,7 @@ print_basic (gnutls_string * str, const char *prefix, int 
type,
 
 
 static void
-print_altname (gnutls_string * str, const char *prefix, int altname_type,
+print_altname (gnutls_buffer_st * str, const char *prefix, int altname_type,
               cert_type_t cert)
 {
   unsigned int altname_idx;
@@ -705,7 +705,7 @@ print_altname (gnutls_string * str, const char *prefix, int 
altname_type,
 }
 
 static void
-print_extensions (gnutls_string * str, const char *prefix, int type,
+print_extensions (gnutls_buffer_st * str, const char *prefix, int type,
                  cert_type_t cert)
 {
   int i, err;
@@ -962,7 +962,7 @@ print_extensions (gnutls_string * str, const char *prefix, 
int type,
 }
 
 static void
-print_cert (gnutls_string * str, gnutls_x509_crt_t cert, int notsigned)
+print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned)
 {
   /* Version. */
   {
@@ -1222,7 +1222,7 @@ print_cert (gnutls_string * str, gnutls_x509_crt_t cert, 
int notsigned)
 }
 
 static void
-print_fingerprint (gnutls_string * str, gnutls_x509_crt_t cert,
+print_fingerprint (gnutls_buffer_st * str, gnutls_x509_crt_t cert,
                   gnutls_digest_algorithm_t algo)
 {
   int err;
@@ -1245,7 +1245,7 @@ print_fingerprint (gnutls_string * str, gnutls_x509_crt_t 
cert,
 }
 
 static void
-print_keyid (gnutls_string * str, gnutls_x509_crt_t cert)
+print_keyid (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
 {
   int err;
   char buffer[20];
@@ -1264,7 +1264,7 @@ print_keyid (gnutls_string * str, gnutls_x509_crt_t cert)
 }
 
 static void
-print_other (gnutls_string * str, gnutls_x509_crt_t cert, int notsigned)
+print_other (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned)
 {
   if (!notsigned)
     {
@@ -1275,7 +1275,7 @@ print_other (gnutls_string * str, gnutls_x509_crt_t cert, 
int notsigned)
 }
 
 static void
-print_oneline (gnutls_string * str, gnutls_x509_crt_t cert)
+print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
 {
   /* Subject. */
   {
@@ -1462,32 +1462,32 @@ gnutls_x509_crt_print (gnutls_x509_crt_t cert,
                       gnutls_certificate_print_formats_t format,
                       gnutls_datum_t * out)
 {
-  gnutls_string str;
+  gnutls_buffer_st str;
 
   if (format == GNUTLS_CRT_PRINT_FULL
       || format == GNUTLS_CRT_PRINT_UNSIGNED_FULL)
     {
-      _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free);
+      _gnutls_buffer_init (&str);
 
-      _gnutls_string_append_str (&str, _("X.509 Certificate Information:\n"));
+      _gnutls_buffer_append_str (&str, _("X.509 Certificate Information:\n"));
 
       print_cert (&str, cert, format == GNUTLS_CRT_PRINT_UNSIGNED_FULL);
 
-      _gnutls_string_append_str (&str, _("Other Information:\n"));
+      _gnutls_buffer_append_str (&str, _("Other Information:\n"));
 
       print_other (&str, cert, format == GNUTLS_CRT_PRINT_UNSIGNED_FULL);
 
-      _gnutls_string_append_data (&str, "\0", 1);
+      _gnutls_buffer_append_data (&str, "\0", 1);
       out->data = str.data;
       out->size = strlen (str.data);
     }
   else if (format == GNUTLS_CRT_PRINT_ONELINE)
     {
-      _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free);
+      _gnutls_buffer_init (&str);
 
       print_oneline (&str, cert);
 
-      _gnutls_string_append_data (&str, "\0", 1);
+      _gnutls_buffer_append_data (&str, "\0", 1);
       out->data = str.data;
       out->size = strlen (str.data);
     }
@@ -1503,7 +1503,7 @@ gnutls_x509_crt_print (gnutls_x509_crt_t cert,
 #ifdef ENABLE_PKI
 
 static void
-print_crl (gnutls_string * str, gnutls_x509_crl_t crl, int notsigned)
+print_crl (gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
 {
   /* Version. */
   {
@@ -1818,16 +1818,16 @@ gnutls_x509_crl_print (gnutls_x509_crl_t crl,
                       gnutls_certificate_print_formats_t format,
                       gnutls_datum_t * out)
 {
-  gnutls_string str;
+  gnutls_buffer_st str;
 
-  _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free);
+  _gnutls_buffer_init (&str);
 
-  _gnutls_string_append_str
+  _gnutls_buffer_append_str
     (&str, _("X.509 Certificate Revocation List Information:\n"));
 
   print_crl (&str, crl, format == GNUTLS_CRT_PRINT_UNSIGNED_FULL);
 
-  _gnutls_string_append_data (&str, "\0", 1);
+  _gnutls_buffer_append_data (&str, "\0", 1);
   out->data = str.data;
   out->size = strlen (str.data);
 
@@ -1835,7 +1835,7 @@ gnutls_x509_crl_print (gnutls_x509_crl_t crl,
 }
 
 static void
-print_crq (gnutls_string * str, gnutls_x509_crq_t cert)
+print_crq (gnutls_buffer_st * str, gnutls_x509_crq_t cert)
 {
   /* Version. */
   {
@@ -2075,7 +2075,7 @@ print_crq (gnutls_string * str, gnutls_x509_crq_t cert)
 }
 
 static void
-print_crq_other (gnutls_string * str, gnutls_x509_crq_t crq)
+print_crq_other (gnutls_buffer_st * str, gnutls_x509_crq_t crq)
 {
   int err;
   size_t size = 0;
@@ -2132,20 +2132,20 @@ gnutls_x509_crq_print (gnutls_x509_crq_t crq,
                       gnutls_certificate_print_formats_t format,
                       gnutls_datum_t * out)
 {
-  gnutls_string str;
+  gnutls_buffer_st str;
 
-  _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free);
+  _gnutls_buffer_init (&str);
 
-  _gnutls_string_append_str
+  _gnutls_buffer_append_str
     (&str, _("PKCS #10 Certificate Request Information:\n"));
 
   print_crq (&str, crq);
 
-  _gnutls_string_append_str (&str, _("Other Information:\n"));
+  _gnutls_buffer_append_str (&str, _("Other Information:\n"));
 
   print_crq_other (&str, crq);
 
-  _gnutls_string_append_data (&str, "\0", 1);
+  _gnutls_buffer_append_data (&str, "\0", 1);
   out->data = str.data;
   out->size = strlen (str.data);
 
diff --git a/libextra/ext_inner_application.c b/libextra/ext_inner_application.c
index 0dcc9ac..bad812e 100644
--- a/libextra/ext_inner_application.c
+++ b/libextra/ext_inner_application.c
@@ -31,11 +31,34 @@
 #define NO 0
 #define YES 1
 
-int
+static int _gnutls_inner_application_recv_params (gnutls_session_t session,
+                                          const opaque * data,
+                                          size_t data_size);
+static int _gnutls_inner_application_send_params (gnutls_session_t session,
+                                          opaque * data, size_t);
+static int ia_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv);
+static int ia_pack(extension_priv_data_t _priv, gnutls_buffer_st* ps);
+static void ia_deinit_data(extension_priv_data_t priv);
+
+extension_entry_st ext_mod_ia = {
+    .name = "INNER APPLICATION",
+    .type = GNUTLS_EXTENSION_INNER_APPLICATION,
+    .parse_type = GNUTLS_EXT_TLS,
+
+    .recv_func = _gnutls_inner_application_recv_params,
+    .send_func = _gnutls_inner_application_send_params,
+    .pack_func = ia_pack,
+    .unpack_func = ia_unpack,
+    .deinit_func = ia_deinit_data,
+};
+
+static int
 _gnutls_inner_application_recv_params (gnutls_session_t session,
                                       const opaque * data, size_t data_size)
 {
-  tls_ext_st *ext = &session->security_parameters.extensions;
+  extension_priv_data_t epriv;
+  ia_ext_st *priv;
+  int ret;
 
   if (data_size != 1)
     {
@@ -43,13 +66,29 @@ _gnutls_inner_application_recv_params (gnutls_session_t 
session,
       return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
     }
 
-  ext->gnutls_ia_peer_enable = 1;
-  ext->gnutls_ia_peer_allowskip = 0;
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+  if (ret < 0)
+    {
+      priv = gnutls_calloc(1, sizeof(*priv));
+      if (priv == NULL)
+        {
+          gnutls_assert();
+          return GNUTLS_E_MEMORY_ERROR;
+        }
+
+      epriv.ptr = priv;
+      _gnutls_ext_set_session_data(session, 
GNUTLS_EXTENSION_INNER_APPLICATION, epriv);
+    }
+  else
+    priv = epriv.ptr;
+
+  priv->flags |= IA_PEER_ENABLE;
+  priv->flags &= ~IA_PEER_ALLOW_SKIP;
 
   switch ((unsigned char) *data)
     {
-    case NO:                   /* Peer's ia_on_resume == no */
-      ext->gnutls_ia_peer_allowskip = 1;
+    case NO: /* Peer's ia_on_resume == no */
+      priv->flags |= IA_PEER_ALLOW_SKIP;
       break;
 
     case YES:
@@ -59,17 +98,36 @@ _gnutls_inner_application_recv_params (gnutls_session_t 
session,
       gnutls_assert ();
     }
 
+
   return 0;
 }
 
 
 /* returns data_size or a negative number on failure
  */
-int
+static int
 _gnutls_inner_application_send_params (gnutls_session_t session,
                                       opaque * data, size_t data_size)
 {
-  tls_ext_st *ext = &session->security_parameters.extensions;
+  extension_priv_data_t epriv;
+  ia_ext_st * priv = NULL;
+  int ret;
+
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+  if (ret < 0)
+    {
+      priv = gnutls_calloc(1, sizeof(*priv));
+      if (priv == NULL)
+        {
+          gnutls_assert();
+          return GNUTLS_E_MEMORY_ERROR;
+        }
+
+      epriv.ptr = priv;
+      _gnutls_ext_set_session_data(session, 
GNUTLS_EXTENSION_INNER_APPLICATION, epriv);
+    }
+  else
+    priv = epriv.ptr;
 
   /* Set ext->gnutls_ia_enable depending on whether we have a TLS/IA
      credential in the session. */
@@ -77,29 +135,31 @@ _gnutls_inner_application_send_params (gnutls_session_t 
session,
   if (session->security_parameters.entity == GNUTLS_CLIENT)
     {
       gnutls_ia_client_credentials_t cred = (gnutls_ia_client_credentials_t)
-       _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
+        _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
 
       if (cred)
-       ext->gnutls_ia_enable = 1;
+        priv->flags |= IA_ENABLE;
     }
-  else
+  else /* SERVER */
     {
-      gnutls_ia_server_credentials_t cred = (gnutls_ia_server_credentials_t)
-       _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
+      gnutls_ia_server_credentials_t cred;
+
+      cred = (gnutls_ia_server_credentials_t)
+        _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
 
       if (cred)
-       ext->gnutls_ia_enable = 1;
+        priv->flags |= IA_PEER_ENABLE;
     }
 
   /* If we don't want gnutls_ia locally, or we are a server and the
    * client doesn't want it, don't advertise TLS/IA support at all, as
    * required. */
 
-  if (!ext->gnutls_ia_enable)
+  if (!(priv->flags & IA_ENABLE))
     return 0;
 
   if (session->security_parameters.entity == GNUTLS_SERVER &&
-      !ext->gnutls_ia_peer_enable)
+      !(priv->flags & IA_PEER_ENABLE))
     return 0;
 
   /* We'll advertise. Check if there's room in the hello buffer. */
@@ -119,8 +179,8 @@ _gnutls_inner_application_send_params (gnutls_session_t 
session,
 
       /* Client: value follows local setting */
 
-      if (ext->gnutls_ia_allowskip)
-       *data = NO;
+      if (priv->flags & IA_ALLOW_SKIP)
+        *data = NO;
     }
   else
     {
@@ -137,11 +197,60 @@ _gnutls_inner_application_send_params (gnutls_session_t 
session,
        * always skip IA on resumption, because recv_ext isn't even called
        * to record the peer's support for IA at all. Simon? */
 
-      if (ext->gnutls_ia_allowskip &&
-         ext->gnutls_ia_peer_allowskip &&
-         session->internals.resumed == RESUME_TRUE)
-       *data = NO;
+      if ((priv->flags & IA_ALLOW_SKIP) &&
+        (priv->flags & IA_PEER_ALLOW_SKIP) &&
+        session->internals.resumed == RESUME_TRUE)
+        *data = NO;
     }
 
   return 1;
 }
+
+static void ia_deinit_data(extension_priv_data_t priv)
+{
+    gnutls_free(priv.ptr);
+}
+
+static int ia_pack(extension_priv_data_t epriv, gnutls_buffer_st* ps)
+{
+ia_ext_st* priv = epriv.ptr;
+int ret;
+
+  BUFFER_APPEND_NUM(ps, priv->flags);
+  BUFFER_APPEND_PFX(ps, priv->inner_secret, GNUTLS_MASTER_SIZE);
+
+  return 0;
+}
+
+static int ia_unpack(gnutls_buffer_st* ps, extension_priv_data_t* _priv)
+{
+ia_ext_st* priv;
+int size, ret;
+extension_priv_data_t epriv;
+
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+      gnutls_assert();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  BUFFER_POP_NUM(ps, priv->flags);
+  BUFFER_POP_NUM(ps, size);
+  if (size != GNUTLS_MASTER_SIZE)
+    {
+      gnutls_assert();
+      return GNUTLS_E_PARSING_ERROR;
+    }
+  BUFFER_POP(ps, priv->inner_secret, GNUTLS_MASTER_SIZE);
+
+  epriv.ptr = priv;
+  *_priv = epriv;
+  
+  return 0;
+
+error:
+  gnutls_free(priv);
+  return ret;
+}
+
diff --git a/libextra/ext_inner_application.h b/libextra/ext_inner_application.h
index a75ee60..3a037cd 100644
--- a/libextra/ext_inner_application.h
+++ b/libextra/ext_inner_application.h
@@ -21,8 +21,40 @@
  *
  */
 
-int _gnutls_inner_application_recv_params (gnutls_session_t session,
-                                          const opaque * data,
-                                          size_t data_size);
-int _gnutls_inner_application_send_params (gnutls_session_t session,
-                                          opaque * data, size_t);
+#ifndef EXT_IA_H
+#define EXT_IA_H
+
+#include <gnutls_extensions.h>
+
+#define IA_PEER_ENABLE (1 << 1)
+#define IA_PEER_ALLOW_SKIP (1 << 2)
+#define IA_ENABLE (1 << 3)
+#define IA_ALLOW_SKIP (1 << 4)
+
+extension_entry_st ext_mod_ia;
+
+typedef struct {
+  unsigned int flags;
+  /* For TLS/IA.  XXX: Move to IA credential? */
+  opaque inner_secret[GNUTLS_MASTER_SIZE];
+} ia_ext_st;
+
+inline static void _gnutls_ia_derive_inner_secret(gnutls_session_t session)
+{
+extension_priv_data_t epriv;
+ia_ext_st *priv;
+int ret;
+  
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+  if (ret < 0)
+    {
+      return ;
+    }
+  priv = epriv.ptr;
+  
+  memcpy (priv->inner_secret,
+         session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
+
+}
+
+#endif
diff --git a/libextra/gnutls_extra.c b/libextra/gnutls_extra.c
index f8866cf..490f0c5 100644
--- a/libextra/gnutls_extra.c
+++ b/libextra/gnutls_extra.c
@@ -126,11 +126,7 @@ gnutls_global_init_extra (void)
   if (_gnutls_init_extra != 1)
     return 0;
 
-  ret = gnutls_ext_register (GNUTLS_EXTENSION_INNER_APPLICATION,
-                            "INNER_APPLICATION",
-                            GNUTLS_EXT_TLS,
-                            _gnutls_inner_application_recv_params,
-                            _gnutls_inner_application_send_params);
+  ret = _gnutls_ext_register (&ext_mod_ia);
   if (ret != GNUTLS_E_SUCCESS)
     return ret;
 
diff --git a/libextra/gnutls_ia.c b/libextra/gnutls_ia.c
index 804ed3f..f3f1e4a 100644
--- a/libextra/gnutls_ia.c
+++ b/libextra/gnutls_ia.c
@@ -26,6 +26,7 @@
 #include "gnutls_num.h"
 #include "gnutls_state.h"
 #include <gnutls/extra.h>
+#include <ext_inner_application.h>
 
 #define CHECKSUM_SIZE 12
 
@@ -171,6 +172,16 @@ _gnutls_ia_prf (gnutls_session_t session,
   int ret;
   opaque *seed;
   size_t seedsize = 2 * GNUTLS_RANDOM_SIZE + extra_size;
+  extension_priv_data_t epriv;
+  ia_ext_st *priv;
+
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
 
   seed = gnutls_malloc (seedsize);
   if (!seed)
@@ -185,7 +196,7 @@ _gnutls_ia_prf (gnutls_session_t session,
          session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);
   memcpy (seed + 2 * GNUTLS_RANDOM_SIZE, extra, extra_size);
 
-  ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
+  ret = _gnutls_PRF (session, priv->inner_secret,
                     GNUTLS_MASTER_SIZE,
                     label, label_size, seed, seedsize, outsize, out);
 
@@ -213,13 +224,25 @@ gnutls_ia_permute_inner_secret (gnutls_session_t session,
                                size_t session_keys_size,
                                const char *session_keys)
 {
+  extension_priv_data_t epriv;
+  ia_ext_st *priv;
+  int ret;
+
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
+
   return _gnutls_ia_prf (session,
                         sizeof (inner_permutation_label) - 1,
                         inner_permutation_label,
                         session_keys_size,
                         session_keys,
                         GNUTLS_RANDOM_SIZE,
-                        session->security_parameters.inner_secret);
+                        priv->inner_secret);
 }
 
 /**
@@ -261,8 +284,19 @@ gnutls_ia_generate_challenge (gnutls_session_t session,
 void
 gnutls_ia_extract_inner_secret (gnutls_session_t session, char *buffer)
 {
-  memcpy (buffer, session->security_parameters.inner_secret,
-         GNUTLS_MASTER_SIZE);
+  extension_priv_data_t epriv;
+  ia_ext_st *priv;
+  int ret;
+
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return;
+    }
+  priv = epriv.ptr;
+
+  memcpy (buffer, priv->inner_secret, GNUTLS_MASTER_SIZE);
 }
 
 /**
@@ -290,8 +324,18 @@ gnutls_ia_endphase_send (gnutls_session_t session, int 
final_p)
     sizeof (server_finished_label);
   ssize_t len;
   int ret;
+  extension_priv_data_t epriv;
+  ia_ext_st *priv;
+
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
 
-  ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
+  ret = _gnutls_PRF (session, priv->inner_secret,
                     GNUTLS_MASTER_SIZE, label, size_of_label - 1,
                     /* XXX specification unclear on seed. */
                     "", 0, CHECKSUM_SIZE, local_checksum);
@@ -343,8 +387,18 @@ gnutls_ia_verify_endphase (gnutls_session_t session, const 
char *checksum)
   int size_of_label = client ? sizeof (server_finished_label) :
     sizeof (client_finished_label);
   int ret;
+  extension_priv_data_t epriv;
+  ia_ext_st *priv;
 
-  ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
+  ret = _gnutls_ext_get_session_data( session, 
GNUTLS_EXTENSION_INNER_APPLICATION, &epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
+
+  ret = _gnutls_PRF (session, priv->inner_secret,
                     GNUTLS_MASTER_SIZE,
                     label, size_of_label - 1,
                     "", 0, CHECKSUM_SIZE, local_checksum);
@@ -610,22 +664,32 @@ _gnutls_ia_server_handshake (gnutls_session_t session)
 int
 gnutls_ia_handshake_p (gnutls_session_t session)
 {
-  tls_ext_st *ext = &session->security_parameters.extensions;
+  extension_priv_data_t epriv;
+  ia_ext_st * priv;
+  int ret;
+
+  ret = _gnutls_ext_get_session_data( session, GNUTLS_EXTENSION_SERVER_NAME, 
&epriv);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+  priv = epriv.ptr;
 
   /* Either local side or peer doesn't do TLS/IA: don't do IA */
 
-  if (!ext->gnutls_ia_enable || !ext->gnutls_ia_peer_enable)
+  if (!(priv->flags & IA_ENABLE) || !(priv->flags & IA_PEER_ENABLE))
     return 0;
 
   /* Not resuming or we don't allow skipping on resumption locally: do IA */
 
-  if (!ext->gnutls_ia_allowskip || !gnutls_session_is_resumed (session))
+  if (!(priv->flags & IA_ALLOW_SKIP) || !gnutls_session_is_resumed (session))
     return 1;
 
   /* If we're resuming and we and the peer both allow skipping on resumption: 
    * don't do IA */
 
-  return !ext->gnutls_ia_peer_allowskip;
+  return !(priv->flags & IA_PEER_ALLOW_SKIP);
 }
 
 
@@ -902,10 +966,24 @@ gnutls_ia_get_server_avp_ptr 
(gnutls_ia_server_credentials_t cred)
  * calling gnutls_ia_handshake() or one of the lower level gnutls_ia_*
  * functions.
  **/
-void
-gnutls_ia_enable (gnutls_session_t session, int allow_skip_on_resume)
+void gnutls_ia_enable (gnutls_session_t session, int allow_skip_on_resume)
 {
-  session->security_parameters.extensions.gnutls_ia_enable = 1;
-  session->security_parameters.extensions.gnutls_ia_allowskip =
-    allow_skip_on_resume;
+  extension_priv_data_t epriv;
+  ia_ext_st * priv;
+
+  priv = gnutls_calloc(1, sizeof(*priv));
+  if (priv == NULL)
+    {
+      gnutls_assert();
+      return;
+    }
+
+  epriv.ptr = priv;
+
+  priv->flags |= IA_ENABLE;
+  if (allow_skip_on_resume)
+    priv->flags |= IA_ALLOW_SKIP;
+
+  _gnutls_ext_set_session_data(session, GNUTLS_EXTENSION_INNER_APPLICATION, 
epriv);
+
 }
diff --git a/src/cli.c b/src/cli.c
index 4d90b43..f0eba23 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -601,14 +601,8 @@ init_tls_session (const char *hostname)
        }
     }
 
-#ifdef ENABLE_OPRFI
-  if (info.opaque_prf_input)
-    gnutls_oprfi_enable_client (session, strlen (info.opaque_prf_input),
-                               info.opaque_prf_input);
-#endif
-
 #ifdef ENABLE_SESSION_TICKET
-  if (!info.noticket)
+  if (disable_extensions ==0 && !info.noticket)
     gnutls_session_ticket_enable_client (session);
 #endif
 
@@ -774,6 +768,7 @@ main (int argc, char **argv)
                                   &session_data_size);
 
          gnutls_session_get_id (hd.session, NULL, &session_id_size);
+
          session_id = malloc (session_id_size);
          gnutls_session_get_id (hd.session, session_id, &session_id_size);
 
diff --git a/src/serv.c b/src/serv.c
index a2457ea..eb7b892 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -333,29 +333,6 @@ static int comp_priority[PRI_MAX];
 static int mac_priority[PRI_MAX];
 static int cert_type_priority[PRI_MAX];
 
-#if ENABLE_OPRFI
-int
-oprfi_callback (gnutls_session_t session,
-               void *userdata,
-               size_t oprfi_len,
-               const unsigned char *in_oprfi, unsigned char *out_oprfi)
-{
-  size_t ourlen = strlen (info.opaque_prf_input);
-  size_t i;
-
-  printf ("- Received Opaque PRF data of %d bytes\n", oprfi_len);
-  printf ("  data: ");
-  for (i = 0; i < oprfi_len; i++)
-    printf ("%02x", in_oprfi[i]);
-  printf ("\n");
-
-  memset (out_oprfi, 0, oprfi_len);
-  strncpy (out_oprfi, info.opaque_prf_input, oprfi_len);
-
-  return 0;
-}
-#endif
-
 static gnutls_session_t
 initialize_session (void)
 {
@@ -420,11 +397,6 @@ initialize_session (void)
        gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
     }
 
-#ifdef ENABLE_OPRFI
-  if (info.opaque_prf_input)
-    gnutls_oprfi_enable_server (session, oprfi_callback, NULL);
-#endif
-
   return session;
 }
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 165370a..a6dcb33 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -83,10 +83,6 @@ endif
 tlsia_LDADD = ../libextra/libgnutls-extra.la $(LDADD) $(LTLIBREADLINE)
 endif
 
-if ENABLE_OPRFI
-ctests +=  oprfi
-endif
-
 check_PROGRAMS = $(ctests)
 dist_check_SCRIPTS = rfc2253-escape-test
 
diff --git a/tests/oprfi.c b/tests/oprfi.c
deleted file mode 100644
index ea6b8e4..0000000
--- a/tests/oprfi.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
- */
-
-/* Parts copied from GnuTLS example programs. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <gnutls/gnutls.h>
-
-#include "utils.h"
-
-static void
-tls_log_func (int level, const char *str)
-{
-  fprintf (stderr, "|<%d>| %s", level, str);
-}
-
-/* A very basic TLS client, with anonymous authentication.
- */
-
-#define MAX_BUF 1024
-#define MSG "Hello TLS"
-
-/* Connects to the peer and returns a socket
- * descriptor.
- */
-int
-tcp_connect (void)
-{
-  const char *PORT = "5556";
-  const char *SERVER = "127.0.0.1";
-  int err, sd;
-  struct sockaddr_in sa;
-
-  /* connects to server
-   */
-  sd = socket (AF_INET, SOCK_STREAM, 0);
-
-  memset (&sa, '\0', sizeof (sa));
-  sa.sin_family = AF_INET;
-  sa.sin_port = htons (atoi (PORT));
-  inet_pton (AF_INET, SERVER, &sa.sin_addr);
-
-  err = connect (sd, (struct sockaddr *) &sa, sizeof (sa));
-  if (err < 0)
-    {
-      fprintf (stderr, "Connect error\n");
-      exit (1);
-    }
-
-  return sd;
-}
-
-/* closes the given socket descriptor.
- */
-void
-tcp_close (int sd)
-{
-  shutdown (sd, SHUT_RDWR);    /* no more receptions */
-  close (sd);
-}
-
-void
-client (void)
-{
-  int ret, sd, ii;
-  gnutls_session_t session;
-  char buffer[MAX_BUF + 1];
-  gnutls_anon_client_credentials_t anoncred;
-  /* Need to enable anonymous KX specifically. */
-  const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
-
-  gnutls_global_init ();
-
-  gnutls_global_set_log_function (tls_log_func);
-  if (debug)
-    gnutls_global_set_log_level (4711);
-
-  gnutls_anon_allocate_client_credentials (&anoncred);
-
-  /* Initialize TLS session
-   */
-  gnutls_init (&session, GNUTLS_CLIENT);
-
-  /* Use default priorities */
-  gnutls_set_default_priority (session);
-  gnutls_kx_set_priority (session, kx_prio);
-
-  /* put the anonymous credentials to the current session
-   */
-  gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
-
-  gnutls_oprfi_enable_client (session, 3, "foo");
-
-  /* connect to the peer
-   */
-  sd = tcp_connect ();
-
-  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
-
-  /* Perform the TLS handshake
-   */
-  ret = gnutls_handshake (session);
-
-  if (ret < 0)
-    {
-      fail ("client: Handshake failed\n");
-      gnutls_perror (ret);
-      goto end;
-    }
-  else
-    {
-      success ("client: Handshake was completed\n");
-    }
-
-  success ("client: TLS version is: %s\n",
-          gnutls_protocol_get_name (gnutls_protocol_get_version (session)));
-
-  gnutls_record_send (session, MSG, strlen (MSG));
-
-  ret = gnutls_record_recv (session, buffer, MAX_BUF);
-  if (ret == 0)
-    {
-      success ("client: Peer has closed the TLS connection\n");
-      goto end;
-    }
-  else if (ret < 0)
-    {
-      fail ("client: Error: %s\n", gnutls_strerror (ret));
-      goto end;
-    }
-
-  printf ("- Received %d bytes: ", ret);
-  for (ii = 0; ii < ret; ii++)
-    {
-      fputc (buffer[ii], stdout);
-    }
-  fputs ("\n", stdout);
-
-  gnutls_bye (session, GNUTLS_SHUT_RDWR);
-
-end:
-
-  tcp_close (sd);
-
-  gnutls_deinit (session);
-
-  gnutls_anon_free_client_credentials (anoncred);
-
-  gnutls_global_deinit ();
-}
-
-/* This is a sample TLS 1.0 echo server, for anonymous authentication only.
- */
-
-#define SA struct sockaddr
-#define MAX_BUF 1024
-#define PORT 5556              /* listen to 5556 port */
-#define DH_BITS 1024
-
-/* These are global */
-gnutls_anon_server_credentials_t anoncred;
-
-int
-oprfi_callback (gnutls_session_t session,
-               void *userdata,
-               size_t oprfi_len,
-               const unsigned char *in_oprfi, unsigned char *out_oprfi)
-{
-  size_t i;
-
-  puts ("cb");
-
-  for (i = 0; i < oprfi_len; i++)
-    printf ("OPRF[%d]: %02x %03d %c\n", i, in_oprfi[i],
-           in_oprfi[i], in_oprfi[i]);
-
-  memset (out_oprfi, 42, oprfi_len);
-
-  return 0;
-}
-
-gnutls_session_t
-initialize_tls_session (void)
-{
-  gnutls_session_t session;
-  const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
-
-  gnutls_init (&session, GNUTLS_SERVER);
-
-  /* avoid calling all the priority functions, since the defaults
-   * are adequate.
-   */
-  gnutls_set_default_priority (session);
-  gnutls_kx_set_priority (session, kx_prio);
-
-  gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
-
-  gnutls_dh_set_prime_bits (session, DH_BITS);
-
-  gnutls_oprfi_enable_server (session, oprfi_callback, NULL);
-
-  return session;
-}
-
-static gnutls_dh_params_t dh_params;
-
-static int
-generate_dh_params (void)
-{
-  const gnutls_datum_t p3 = { pkcs3, strlen (pkcs3) };
-  /* Generate Diffie-Hellman parameters - for use with DHE
-   * kx algorithms. These should be discarded and regenerated
-   * once a day, once a week or once a month. Depending on the
-   * security requirements.
-   */
-  gnutls_dh_params_init (&dh_params);
-  return gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
-}
-
-int err, listen_sd, i;
-int sd, ret;
-struct sockaddr_in sa_serv;
-struct sockaddr_in sa_cli;
-int client_len;
-char topbuf[512];
-gnutls_session_t session;
-char buffer[MAX_BUF + 1];
-int optval = 1;
-
-void
-server_start (void)
-{
-  /* this must be called once in the program
-   */
-  gnutls_global_init ();
-
-  gnutls_global_set_log_function (tls_log_func);
-  if (debug)
-    gnutls_global_set_log_level (4711);
-
-  gnutls_anon_allocate_server_credentials (&anoncred);
-
-  success ("Launched, generating DH parameters...\n");
-
-  generate_dh_params ();
-
-  gnutls_anon_set_server_dh_params (anoncred, dh_params);
-
-  /* Socket operations
-   */
-  listen_sd = socket (AF_INET, SOCK_STREAM, 0);
-  if (err == -1)
-    {
-      perror ("socket");
-      fail ("server: socket failed\n");
-      return;
-    }
-
-  memset (&sa_serv, '\0', sizeof (sa_serv));
-  sa_serv.sin_family = AF_INET;
-  sa_serv.sin_addr.s_addr = INADDR_ANY;
-  sa_serv.sin_port = htons (PORT);     /* Server Port number */
-
-  setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
-             sizeof (int));
-
-  err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv));
-  if (err == -1)
-    {
-      perror ("bind");
-      fail ("server: bind failed\n");
-      return;
-    }
-
-  err = listen (listen_sd, 1024);
-  if (err == -1)
-    {
-      perror ("listen");
-      fail ("server: listen failed\n");
-      return;
-    }
-
-  success ("server: ready. Listening to port '%d'.\n", PORT);
-}
-
-void
-server (void)
-{
-  client_len = sizeof (sa_cli);
-
-  session = initialize_tls_session ();
-
-  sd = accept (listen_sd, (SA *) & sa_cli, &client_len);
-
-  success ("server: connection from %s, port %d\n",
-          inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,
-                     sizeof (topbuf)), ntohs (sa_cli.sin_port));
-
-  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
-  ret = gnutls_handshake (session);
-  if (ret < 0)
-    {
-      close (sd);
-      gnutls_deinit (session);
-      fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret));
-      return;
-    }
-  success ("server: Handshake was completed\n");
-
-  success ("server: TLS version is: %s\n",
-          gnutls_protocol_get_name (gnutls_protocol_get_version (session)));
-
-  /* see the Getting peer's information example */
-  /* print_info(session); */
-
-  i = 0;
-  for (;;)
-    {
-      memset (buffer, 0, MAX_BUF + 1);
-      ret = gnutls_record_recv (session, buffer, MAX_BUF);
-
-      if (ret == 0)
-       {
-         success ("server: Peer has closed the GnuTLS connection\n");
-         break;
-       }
-      else if (ret < 0)
-       {
-         fail ("server: Received corrupted data(%d). Closing...\n", ret);
-         break;
-       }
-      else if (ret > 0)
-       {
-         /* echo data back to the client
-          */
-         gnutls_record_send (session, buffer, strlen (buffer));
-       }
-    }
-  /* do not wait for the peer to close the connection.
-   */
-  gnutls_bye (session, GNUTLS_SHUT_WR);
-
-  close (sd);
-  gnutls_deinit (session);
-
-  close (listen_sd);
-
-  gnutls_anon_free_server_credentials (anoncred);
-
-  gnutls_global_deinit ();
-
-  success ("server: finished\n");
-}
-
-void
-doit (void)
-{
-  pid_t child;
-
-  server_start ();
-  if (error_count)
-    return;
-
-  child = fork ();
-  if (child < 0)
-    {
-      perror ("fork");
-      fail ("fork");
-      return;
-    }
-
-  if (child)
-    {
-      int status;
-      /* parent */
-      server ();
-      wait (&status);
-    }
-  else
-    client ();
-}
diff --git a/tests/tlsia.c b/tests/tlsia.c
index dd42892..c97ce95 100644
--- a/tests/tlsia.c
+++ b/tests/tlsia.c
@@ -51,6 +51,12 @@
 #define MAX_BUF 1024
 #define MSG "Hello TLS"
 
+static void
+tls_log_func (int level, const char *str)
+{
+  fprintf (stderr, "<%d>| %s", level, str);
+}
+
 static int
 client_avp (gnutls_session_t session, void *ptr,
            const char *last, size_t lastlen, char **new, size_t * newlen)
@@ -117,6 +123,10 @@ client (void)
   const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
 
   ret = gnutls_global_init ();
+  gnutls_global_set_log_function (tls_log_func);
+  if (debug)
+    gnutls_global_set_log_level (2);
+
   if (ret)
     fail ("global_init: %d\n", ret);
   ret = gnutls_global_init_extra ();
@@ -425,6 +435,10 @@ server (void)
   if (ret)
     fail ("global_init_extra: %d\n", ret);
 
+  gnutls_global_set_log_function (tls_log_func);
+  if (debug)
+    gnutls_global_set_log_level (2);
+
   gnutls_anon_allocate_server_credentials (&anoncred);
   gnutls_ia_allocate_server_credentials (&iacred);
 


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]