Imported Upstream version 3.4.11
[platform/upstream/gnutls.git] / lib / ext / session_ticket.c
index 35bad36..585544b 100644 (file)
@@ -33,6 +33,7 @@
 #include <gnutls_mbuffers.h>
 #include <gnutls_extensions.h>
 #include <gnutls_constate.h>
+#include <gnutls_dtls.h>
 
 #ifdef ENABLE_SESSION_TICKETS
 
@@ -97,7 +98,7 @@ decrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv,
        time_t timestamp = gnutls_time(0);
        int ret;
 
-       /* Decrypt encrypted_state using 128-bit AES in CBC mode. */
+       /* Decrypt encrypted_state using 128-bit AES in GCM mode. */
        key.data = (void *) &priv->key[KEY_POS];
        key.size = KEY_SIZE;
        IV.data = ticket->IV;
@@ -118,7 +119,7 @@ decrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv,
        }
        
        _gnutls_cipher_tag(&cipher_hd, final, TAG_SIZE);
-       if (memcmp(ticket->tag, final, TAG_SIZE) != 0) {
+       if (gnutls_memcmp(ticket->tag, final, TAG_SIZE) != 0) {
                gnutls_assert();
                ret = GNUTLS_E_DECRYPTION_FAILED;
                goto cleanup;
@@ -249,7 +250,7 @@ session_ticket_recv_params(gnutls_session_t session,
        if (ret < 0) {
                return 0;
        }
-       priv = epriv.ptr;
+       priv = epriv;
 
        if (!priv->session_ticket_enable)
                return 0;
@@ -257,7 +258,6 @@ session_ticket_recv_params(gnutls_session_t session,
        if (session->security_parameters.entity == GNUTLS_SERVER) {
                struct ticket_st ticket;
                const uint8_t *encrypted_state;
-               int ret;
 
                /* The client requested a new session ticket. */
                if (data_size == 0) {
@@ -336,7 +336,7 @@ session_ticket_send_params(gnutls_session_t session,
                                         GNUTLS_EXTENSION_SESSION_TICKET,
                                         &epriv);
        if (ret >= 0)
-               priv = epriv.ptr;
+               priv = epriv;
 
        if (priv == NULL || !priv->session_ticket_enable)
                return 0;
@@ -351,7 +351,7 @@ session_ticket_send_params(gnutls_session_t session,
                                                         GNUTLS_EXTENSION_SESSION_TICKET,
                                                         &epriv);
                if (ret >= 0)
-                       priv = epriv.ptr;
+                       priv = epriv;
 
                /* no previous data. Just advertize it */
                if (ret < 0)
@@ -380,7 +380,7 @@ session_ticket_send_params(gnutls_session_t session,
 
 static void session_ticket_deinit_data(extension_priv_data_t epriv)
 {
-       session_ticket_ext_st *priv = epriv.ptr;
+       session_ticket_ext_st *priv = epriv;
 
        gnutls_free(priv->session_ticket);
        gnutls_free(priv);
@@ -389,7 +389,7 @@ static void session_ticket_deinit_data(extension_priv_data_t epriv)
 static int
 session_ticket_pack(extension_priv_data_t epriv, gnutls_buffer_st * ps)
 {
-       session_ticket_ext_st *priv = epriv.ptr;
+       session_ticket_ext_st *priv = epriv;
        int ret;
 
        BUFFER_APPEND_PFX4(ps, priv->session_ticket,
@@ -418,7 +418,7 @@ session_ticket_unpack(gnutls_buffer_st * ps, extension_priv_data_t * _priv)
        priv->session_ticket_len = ticket.size;
        BUFFER_POP_NUM(ps, priv->session_ticket_enable);
 
-       epriv.ptr = priv;
+       epriv = priv;
        *_priv = epriv;
 
        return 0;
@@ -450,7 +450,7 @@ int gnutls_session_ticket_key_generate(gnutls_datum_t * key)
 
 /**
  * gnutls_session_ticket_enable_client:
- * @session: is a #gnutls_session_t structure.
+ * @session: is a #gnutls_session_t type.
  *
  * Request that the client should attempt session resumption using
  * SessionTicket.
@@ -476,7 +476,7 @@ int gnutls_session_ticket_enable_client(gnutls_session_t session)
                return GNUTLS_E_MEMORY_ERROR;
        }
        priv->session_ticket_enable = 1;
-       epriv.ptr = priv;
+       epriv = priv;
 
        _gnutls_ext_set_session_data(session,
                                     GNUTLS_EXTENSION_SESSION_TICKET,
@@ -487,12 +487,13 @@ int gnutls_session_ticket_enable_client(gnutls_session_t session)
 
 /**
  * gnutls_session_ticket_enable_server:
- * @session: is a #gnutls_session_t structure.
+ * @session: is a #gnutls_session_t type.
  * @key: key to encrypt session parameters.
  *
  * Request that the server should attempt session resumption using
  * SessionTicket.  @key must be initialized with
- * gnutls_session_ticket_key_generate().
+ * gnutls_session_ticket_key_generate(), and should be overwritten
+ * using gnutls_memset() before being released.
  *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
  * error code.
@@ -516,7 +517,7 @@ gnutls_session_ticket_enable_server(gnutls_session_t session,
                gnutls_assert();
                return GNUTLS_E_MEMORY_ERROR;
        }
-       epriv.ptr = priv;
+       epriv = priv;
 
        memcpy(&priv->key, key->data, key->size);
        priv->session_ticket_enable = 1;
@@ -547,7 +548,7 @@ int _gnutls_send_new_session_ticket(gnutls_session_t session, int again)
                                                 &epriv);
                if (ret < 0)
                        return 0;
-               priv = epriv.ptr;
+               priv = epriv;
 
                if (!priv->session_ticket_renew)
                        return 0;
@@ -639,11 +640,22 @@ int _gnutls_recv_new_session_ticket(gnutls_session_t session)
                gnutls_assert();
                return 0;
        }
-       priv = epriv.ptr;
+       priv = epriv;
 
        if (!priv->session_ticket_renew)
                return 0;
 
+       /* This is the last flight and peer cannot be sure
+        * we have received it unless we notify him. So we
+        * wait for a message and retransmit if needed. */
+       if (IS_DTLS(session) && !_dtls_is_async(session) &&
+           (gnutls_record_check_pending(session) +
+            record_check_unprocessed(session)) == 0) {
+               ret = _dtls_wait_and_retransmit(session);
+               if (ret < 0)
+                       return gnutls_assert_val(ret);
+       }
+
        ret = _gnutls_recv_handshake(session,
                                     GNUTLS_HANDSHAKE_NEW_SESSION_TICKET,
                                     0, &buf);