diff --git a/doc/Makefile.am b/doc/Makefile.am
index 87303d1..e5fada7 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -686,6 +686,7 @@ FUNCS += functions/gnutls_session_set_data
 FUNCS += functions/gnutls_session_get_data
 FUNCS += functions/gnutls_session_get_data2
 FUNCS += functions/gnutls_session_get_random
+FUNCS += functions/gnutls_session_set_master
 FUNCS += functions/gnutls_session_get_id
 FUNCS += functions/gnutls_session_channel_binding
 FUNCS += functions/gnutls_session_is_resumed
diff --git a/lib/algorithms.h b/lib/algorithms.h
index 9fe0272..748629c 100644
--- a/lib/algorithms.h
+++ b/lib/algorithms.h
@@ -69,6 +69,11 @@ gnutls_kx_algorithm_t _gnutls_cipher_suite_get_kx_algo (const uint8_t suite[2]);
 gnutls_mac_algorithm_t _gnutls_cipher_suite_get_mac_algo (const
                                                           uint8_t suite[2]);
 
+int
+_gnutls_cipher_suite_get_id (gnutls_kx_algorithm_t kx_algorithm,
+                              gnutls_cipher_algorithm_t cipher_algorithm,
+                              gnutls_mac_algorithm_t mac_algorithm, uint8_t suite[2]);
+
 /* Functions for ciphers. */
 int _gnutls_cipher_is_block (gnutls_cipher_algorithm_t algorithm);
 int _gnutls_cipher_algo_is_aead (gnutls_cipher_algorithm_t algorithm);
diff --git a/lib/algorithms/ciphersuites.c b/lib/algorithms/ciphersuites.c
index 3c5a79d..678812e 100644
--- a/lib/algorithms/ciphersuites.c
+++ b/lib/algorithms/ciphersuites.c
@@ -726,6 +726,35 @@ const gnutls_cipher_suite_entry * ce;
     return ce->name + sizeof ("GNUTLS_") - 1;
 }
 
+/*-
+ * _gnutls_cipher_suite_get_id:
+ * @kx_algorithm: is a Key exchange algorithm
+ * @cipher_algorithm: is a cipher algorithm
+ * @mac_algorithm: is a MAC algorithm
+ * @suite: The id to be returned
+ *
+ * It fills @suite with the ID of the ciphersuite of the provided parameters.
+ *
+ * Returns: 0 on success or a negative error code otherwise.
+ -*/
+int
+_gnutls_cipher_suite_get_id (gnutls_kx_algorithm_t kx_algorithm,
+                              gnutls_cipher_algorithm_t cipher_algorithm,
+                              gnutls_mac_algorithm_t mac_algorithm, uint8_t suite[2])
+{
+const gnutls_cipher_suite_entry * ce;
+
+  ce = cipher_suite_get (kx_algorithm, cipher_algorithm, mac_algorithm);
+  if (ce == NULL)
+    return GNUTLS_E_INVALID_REQUEST;
+  else
+    {
+      suite[0] = ce->id[0];
+      suite[1] = ce->id[1];
+    }
+  return 0;
+}
+
 /**
  * gnutls_cipher_suite_info:
  * @idx: index of cipher suite to get information about, starts on 0.
diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c
index a152901..01203d8 100644
--- a/lib/algorithms/protocols.c
+++ b/lib/algorithms/protocols.c
@@ -43,6 +43,7 @@ static const gnutls_version_entry sup_versions[] = {
   {"TLS1.0", GNUTLS_TLS1, 3, 1, GNUTLS_STREAM, 1},
   {"TLS1.1", GNUTLS_TLS1_1, 3, 2, GNUTLS_STREAM, 1},
   {"TLS1.2", GNUTLS_TLS1_2, 3, 3, GNUTLS_STREAM, 1},
+  {"DTLS0.9", GNUTLS_DTLS0_9, 1, 0, GNUTLS_DGRAM, 1}, /* Cisco AnyConnect (based on about OpenSSL 0.9.8e) */
   {"DTLS1.0", GNUTLS_DTLS1_0, 254, 255, GNUTLS_DGRAM, 1}, /* 1.1 over datagram */
   {0, 0, 0, 0, 0}
 };
@@ -242,6 +243,7 @@ _gnutls_version_has_selectable_prf (gnutls_protocol_t version)
 {
   switch (version)
     {
+    case GNUTLS_DTLS0_9:
     case GNUTLS_DTLS1_0:
     case GNUTLS_TLS1_1:
     case GNUTLS_TLS1_0:
@@ -259,6 +261,7 @@ _gnutls_version_has_selectable_sighash (gnutls_protocol_t version)
 {
   switch (version)
     {
+    case GNUTLS_DTLS0_9:
     case GNUTLS_DTLS1_0:
     case GNUTLS_TLS1_1:
     case GNUTLS_TLS1_0:
diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c
index 5ef0c74..c9d6515 100644
--- a/lib/gnutls_constate.c
+++ b/lib/gnutls_constate.c
@@ -466,7 +466,8 @@ _gnutls_epoch_set_keys (gnutls_session_t session, uint16_t epoch)
 	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
+	dst->version = src->version; \
+	dst->master_set = src->master_set;
 
 static void
 _gnutls_set_resumed_parameters (gnutls_session_t session)
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 25520c4..b96e67b 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -1191,7 +1191,8 @@ _gnutls_handshake_hash_add_recvd (gnutls_session_t session,
 {
   int ret;
 
-  if (recv_type == GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST ||
+  if ((gnutls_protocol_get_version (session) != GNUTLS_DTLS0_9 &&
+       recv_type == GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST) ||
       recv_type == GNUTLS_HANDSHAKE_HELLO_REQUEST)
     return 0;
 
@@ -1199,11 +1200,13 @@ _gnutls_handshake_hash_add_recvd (gnutls_session_t session,
 
   session->internals.handshake_hash_buffer_prev_len = session->internals.handshake_hash_buffer.length;
 
-  ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
-    header, header_size);
-  if (ret < 0)
-    return gnutls_assert_val(ret);
-
+  if (gnutls_protocol_get_version (session) != GNUTLS_DTLS0_9)
+    {
+      ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
+        header, header_size);
+      if (ret < 0)
+        return gnutls_assert_val(ret);
+  }
   if (datalen > 0)
     {
       ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
@@ -1231,6 +1234,16 @@ _gnutls_handshake_hash_add_sent (gnutls_session_t session,
     {
       CHECK_SIZE(datalen);
 
+      if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9) {
+	      /* Old DTLS doesn't include the header in the MAC */
+	      if (datalen <= 12) {
+		      gnutls_assert ();
+		      return GNUTLS_E_INVALID_REQUEST;
+	      }
+	      dataptr += 12;
+	      datalen -= 12;
+      }
+
       ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
                                        dataptr, datalen);
       if (ret < 0)
@@ -1402,7 +1415,8 @@ _gnutls_client_set_ciphersuite (gnutls_session_t session, uint8_t suite[2])
   /* check if the credentials (username, public key etc.) are ok.
    * Actually checks if they exist.
    */
-  if (_gnutls_get_kx_cred
+  if (!session->internals.resumed_security_parameters.master_set &&
+      _gnutls_get_kx_cred
       (session,
        _gnutls_cipher_suite_get_kx_algo
        (session->security_parameters.cipher_suite), &err) == NULL
@@ -1823,6 +1837,8 @@ _gnutls_send_client_hello (gnutls_session_t session, int again)
            */
           if (!IS_DTLS(session))
             _gnutls_record_set_default_version (session, 3, 0);
+          else if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+            _gnutls_record_set_default_version (session, 1, 0);
           else
             _gnutls_record_set_default_version (session, 254, 255);
         }
@@ -2580,12 +2596,20 @@ send_change_cipher_spec (gnutls_session_t session, int again)
       if (bufel == NULL)
         return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
-      _mbuffer_set_uhead_size(bufel, 1);
+      if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+        _mbuffer_set_uhead_size(bufel, 3);
+      else
+        _mbuffer_set_uhead_size(bufel, 1);
       _mbuffer_set_udata_size(bufel, 0);
 
       data = _mbuffer_get_uhead_ptr (bufel);
       
       data[0] = 1;
+      if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+        {
+          _gnutls_write_uint16 (session->internals.dtls.hsk_write_seq, &data[1]);
+          session->internals.dtls.hsk_write_seq++;
+       }
 
       ret = _gnutls_handshake_io_cache_int (session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, bufel);
       if (ret < 0)
@@ -2669,7 +2693,7 @@ _gnutls_recv_handshake_final (gnutls_session_t session, int init)
 {
   int ret = 0;
   uint8_t ch;
-
+  int ccs_len = 1;
 
   switch (STATE)
     {
@@ -2689,7 +2713,10 @@ _gnutls_recv_handshake_final (gnutls_session_t session, int init)
             return gnutls_assert_val(ret);
         }
 
-      ret = _gnutls_recv_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1, &ch, 1, NULL);
+      if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+	      ccs_len = 3;
+
+      ret = _gnutls_recv_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1, &ch, ccs_len, NULL);
       if (ret <= 0)
         {
           ERR ("recv ChangeCipherSpec", ret);
@@ -2714,6 +2741,8 @@ _gnutls_recv_handshake_final (gnutls_session_t session, int init)
           gnutls_assert ();
           return ret;
         }
+      if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+              session->internals.dtls.hsk_read_seq++;
         
     case STATE31:
       STATE = STATE31;
@@ -3149,7 +3178,8 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t session,
 
       /* if it is defined but had no credentials 
        */
-      if (_gnutls_get_kx_cred (session, kx, NULL) == NULL)
+      if (!session->internals.resumed_security_parameters.master_set &&
+          _gnutls_get_kx_cred (session, kx, NULL) == NULL)
         {
           delete = 1;
         }
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 4a60ae0..d82dbd2 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -501,6 +501,7 @@ typedef struct
    * do that? Do they belong in security parameters?
    */
   int do_recv_supplemental, do_send_supplemental;
+  unsigned int master_set:1;
 } security_parameters_st;
 
 struct record_state_st
diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c
index c38de18..2b84da3 100644
--- a/lib/gnutls_kx.c
+++ b/lib/gnutls_kx.c
@@ -73,27 +73,33 @@ send_handshake (gnutls_session_t session, uint8_t * data, size_t size,
 
 #define MASTER_SECRET "master secret"
 #define MASTER_SECRET_SIZE (sizeof(MASTER_SECRET)-1)
-static int generate_normal_master (gnutls_session_t session, int);
+static int generate_normal_master (gnutls_session_t session, gnutls_datum_t*, int);
 
 int
 _gnutls_generate_master (gnutls_session_t session, int keep_premaster)
 {
   if (session->internals.resumed == RESUME_FALSE)
-    return generate_normal_master (session, keep_premaster);
+    return generate_normal_master (session, &session->key->key, keep_premaster);
+  else if (session->internals.resumed_security_parameters.master_set)  {
+    gnutls_datum_t premaster;
+    premaster.size = sizeof(session->internals.resumed_security_parameters.master_secret);
+    premaster.data = session->internals.resumed_security_parameters.master_secret;
+    return generate_normal_master(session, &premaster, 1);
+  }
   return 0;
 }
 
 /* here we generate the TLS Master secret.
  */
-#define PREMASTER session->key->key
 static int
-generate_normal_master (gnutls_session_t session, int keep_premaster)
+generate_normal_master (gnutls_session_t session, gnutls_datum_t *premaster,
+			int keep_premaster)
 {
   int ret = 0;
   char buf[512];
 
-  _gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", PREMASTER.size,
-                    _gnutls_bin2hex (PREMASTER.data, PREMASTER.size, buf,
+  _gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", premaster->size,
+                    _gnutls_bin2hex (premaster->data, premaster->size, buf,
                                      sizeof (buf), NULL));
   _gnutls_hard_log ("INT: CLIENT RANDOM[%d]: %s\n", 32,
                     _gnutls_bin2hex (session->
@@ -114,7 +120,7 @@ generate_normal_master (gnutls_session_t session, int keep_premaster)
               session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
 
       ret =
-        _gnutls_ssl3_generate_random (PREMASTER.data, PREMASTER.size,
+        _gnutls_ssl3_generate_random (premaster->data, premaster->size,
                                       rnd, 2 * GNUTLS_RANDOM_SIZE,
                                       GNUTLS_MASTER_SIZE,
                                       session->
@@ -131,14 +137,14 @@ generate_normal_master (gnutls_session_t session, int keep_premaster)
               session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
 
       ret =
-        _gnutls_PRF (session, PREMASTER.data, PREMASTER.size,
+        _gnutls_PRF (session, premaster->data, premaster->size,
                      MASTER_SECRET, MASTER_SECRET_SIZE,
                      rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE,
                      session->security_parameters.master_secret);
     }
 
   if (!keep_premaster)
-    _gnutls_free_datum (&PREMASTER);
+    _gnutls_free_datum (premaster);
 
   if (ret < 0)
     return ret;
diff --git a/lib/gnutls_session_pack.c b/lib/gnutls_session_pack.c
index 3e89b98..675a8a6 100644
--- a/lib/gnutls_session_pack.c
+++ b/lib/gnutls_session_pack.c
@@ -40,6 +40,7 @@
 #include <gnutls_num.h>
 #include <gnutls_extensions.h>
 #include <gnutls_constate.h>
+#include <algorithms.h>
 
 static int pack_certificate_auth_info (gnutls_session_t,
                                        gnutls_buffer_st * packed_session);
@@ -860,3 +861,71 @@ unpack_security_parameters (gnutls_session_t session, gnutls_buffer_st * ps)
 error:
   return ret;
 }
+
+/**
+ * gnutls_session_set_master:
+ * @session: is a #gnutls_session_t structure.
+ * @entity: GNUTLS_SERVER or GNUTLS_CLIENT
+ * @version: the TLS protocol version
+ * @kx: the key exchange method
+ * @cipher: the cipher
+ * @mac: the MAC algorithm
+ * @comp: the compression method
+ * @master: the master key to use
+ * @session_id: the session identifier
+ *
+ * This function sets the master secret in a session. This is
+ * a function intended for exceptional uses. Do not use this
+ * function unless you are implementing a legacy protocol.
+ * Use gnutls_session_set_data() instead.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ *   an error code is returned.
+ **/
+int
+gnutls_session_set_master (gnutls_session_t session, unsigned int entity,
+                           gnutls_protocol_t version, 
+                           gnutls_kx_algorithm_t kx, 
+                           gnutls_cipher_algorithm_t cipher,
+                           gnutls_mac_algorithm_t mac,
+                           gnutls_compression_method_t comp,
+                           const gnutls_datum_t* master,
+                           const gnutls_datum_t * session_id)
+{
+  int ret;
+
+  memset (&session->internals.resumed_security_parameters, 0,
+          sizeof (session->internals.resumed_security_parameters));
+  
+  session->internals.resumed_security_parameters.entity = entity;
+  session->internals.resumed_security_parameters.kx_algorithm = kx;
+  
+  ret = _gnutls_cipher_suite_get_id(kx, cipher, mac, session->internals.resumed_security_parameters.cipher_suite);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  session->internals.resumed_security_parameters.compression_method = comp;
+  session->internals.resumed_security_parameters.cert_type = GNUTLS_CRT_UNKNOWN;
+  session->internals.resumed_security_parameters.version = version;
+
+  if (master->size != GNUTLS_MASTER_SIZE)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+  memcpy(session->internals.resumed_security_parameters.master_secret, master->data, master->size);
+
+  if (session_id->size > GNUTLS_MAX_SESSION_ID)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+  session->internals.resumed_security_parameters.session_id_size = session_id->size;
+  memcpy(session->internals.resumed_security_parameters.session_id, session_id->data, session_id->size);
+
+  session->internals.resumed_security_parameters.max_record_send_size = 
+  session->internals.resumed_security_parameters.max_record_recv_size = DEFAULT_MAX_RECORD_SIZE;
+
+  session->internals.resumed_security_parameters.timestamp = time(0);
+  session->internals.resumed_security_parameters.master_set = 1;
+
+  session->internals.resumed_security_parameters.ecc_curve = GNUTLS_ECC_CURVE_INVALID;
+
+  return 0;
+}
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 95ce1c7..e7e7180 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -503,6 +503,7 @@ extern "C"
  * @GNUTLS_TLS1_1: TLS version 1.1.
  * @GNUTLS_TLS1_2: TLS version 1.2.
  * @GNUTLS_DTLS1_0: DTLS version 1.0.
+ * @GNUTLS_DTLS0_9: DTLS version 0.9 (Cisco AnyConnect / OpenSSL 0.9.8e).
  * @GNUTLS_VERSION_MAX: Maps to the highest supported TLS version.
  * @GNUTLS_VERSION_UNKNOWN: Unknown SSL/TLS version.
  *
@@ -516,7 +517,8 @@ extern "C"
     GNUTLS_TLS1_1 = 3,
     GNUTLS_TLS1_2 = 4,
     GNUTLS_DTLS1_0 = 5,
-    GNUTLS_VERSION_MAX = GNUTLS_DTLS1_0,
+    GNUTLS_DTLS0_9 = 6,
+    GNUTLS_VERSION_MAX = GNUTLS_DTLS0_9,
     GNUTLS_VERSION_UNKNOWN = 0xff
   } gnutls_protocol_t;
 
@@ -965,6 +967,15 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session);
   void gnutls_session_get_random (gnutls_session_t session, gnutls_datum_t* client, 
                                   gnutls_datum_t* server);
 
+  int gnutls_session_set_master (gnutls_session_t session, unsigned int entity,
+                           gnutls_protocol_t version, 
+                           gnutls_kx_algorithm_t kx, 
+                           gnutls_cipher_algorithm_t cipher,
+                           gnutls_mac_algorithm_t mac,
+                           gnutls_compression_method_t comp,
+                           const gnutls_datum_t* master,
+                           const gnutls_datum_t * session_id);
+
 /* returns the session ID */
 #define GNUTLS_MAX_SESSION_ID 32
   int gnutls_session_get_id (gnutls_session_t session, void *session_id,
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index b2b9825..aa21929 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -788,6 +788,7 @@ GNUTLS_3_0_0 {
 	gnutls_pubkey_verify_hash2;
 	gnutls_pk_to_sign;
 	gnutls_certificate_set_x509_system_trust;
+	gnutls_session_set_master;
 } GNUTLS_2_12;
 
 GNUTLS_PRIVATE {
