fix ticket age check issues

- Ticket age and ticket age add, obfuscated age
  use different unit. Align the units to million
  seconds.
- Add maximum ticket age check. Until now,
  ticket_lifetime is not recorded in server side.
  Check it with maximum ticket_lifetime.
- Free session when error found.

Signed-off-by: Jerry Yu <jerry.h.yu@arm.com>
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 0804152..adedb6d 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -127,13 +127,17 @@
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_offered_psks_check_identity_match_ticket(
                                             mbedtls_ssl_context *ssl,
-                                            mbedtls_ssl_session *session,
                                             const unsigned char *identity,
                                             size_t identity_len,
-                                            uint32_t obfuscated_ticket_age )
+                                            uint32_t obfuscated_ticket_age,
+                                            mbedtls_ssl_session *session )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *ticket_buffer;
+#if defined(MBEDTLS_HAVE_TIME)
+    mbedtls_time_t now;
+    uint64_t age_in_s, age_in_ms, client_age_in_ms;
+#endif
 
     ((void) obfuscated_ticket_age);
 
@@ -178,49 +182,70 @@
     /* We delete the temporary buffer */
     mbedtls_free( ticket_buffer );
 
-    if( ret == 0 )
+    if( ret != 0 )
+        goto exit;
+
+    ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
+#if defined(MBEDTLS_HAVE_TIME)
+    now = mbedtls_time( NULL );
+
+    ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
+    if( now < session->start )
     {
-#if defined(MBEDTLS_HAVE_TIME)
-        mbedtls_time_t now;
-        int64_t diff;
-#endif
-        ret = SSL_TLS1_3_OFFERED_PSK_MATCH;
-#if defined(MBEDTLS_HAVE_TIME)
-        now = mbedtls_time( NULL );
+        MBEDTLS_SSL_DEBUG_MSG(
+            3, ( "Ticket expired: now=%" MBEDTLS_PRINTF_LONGLONG
+                    ", start=%" MBEDTLS_PRINTF_LONGLONG,
+                    (long long)now, (long long)session->start ) );
+        goto exit;
+    }
 
-        /* Check #1:
-         *   Is the time when the ticket was issued later than now?
-         */
-        if( now < session->start )
-        {
-            MBEDTLS_SSL_DEBUG_MSG(
-                3, ( "Ticket expired: now=%" MBEDTLS_PRINTF_LONGLONG
-                        ", start=%" MBEDTLS_PRINTF_LONGLONG,
-                     (long long)now, (long long)session->start ) );
-            ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
-        }
+    age_in_s = (uint64_t)( now - session->start );
 
-        /* Check #2:
-         *   Is the ticket age for the selected PSK identity
-         *   (computed by subtracting ticket_age_add from
-         *   PskIdentity.obfuscated_ticket_age modulo 2^32 )
-         *   within a small tolerance of the time since the
-         *   ticket was issued?
-         */
-        diff = ( now - session->start ) -
-               ( obfuscated_ticket_age - session->ticket_age_add );
+    /* RFC 8446 section 4.6.1
+     *
+     * Servers MUST NOT use any value greater than 604800 seconds (7 days).
+     *
+     * RFC 8446 section 4.2.11.1
+     *
+     * Clients MUST NOT attempt to use tickets which have ages greater than
+     * the "ticket_lifetime" value which was provided with the ticket.
+     *
+     * For time being, the age MUST be less than 604800 seconds (7 days).
+     */
+    if( age_in_s > 604800 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG(
+            3, ( "Ticket expired: Ticket age exceed limitation ticket_age=%lu",
+                 (long unsigned int)age_in_s ) );
+        goto exit;
+    }
 
-        if( diff > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "Ticket age outside tolerance window ( diff=%"
-                      MBEDTLS_PRINTF_LONGLONG" )",
-                  (long long)diff ) );
-            ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
-        }
+    /* RFC 8446 section 4.2.10
+     *
+     * For PSKs provisioned via NewSessionTicket, a server MUST validate that
+     * the ticket age for the selected PSK identity (computed by subtracting
+     * ticket_age_add from PskIdentity.obfuscated_ticket_age modulo 2^32) is
+     * within a small tolerance of the time since the ticket was issued.
+     */
+    age_in_ms = age_in_s * 1000;
+    client_age_in_ms = obfuscated_ticket_age - session->ticket_age_add;
+    if( age_in_ms < client_age_in_ms ||
+        ( age_in_ms - client_age_in_ms ) > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE )
+    {
+        MBEDTLS_SSL_DEBUG_MSG(
+            3, ( "Ticket expired: Ticket age outside tolerance window "
+                     "( diff=%d )",
+                 (int)(age_in_ms - client_age_in_ms ) ) );
+        goto exit;
+    }
+
+    ret = 0;
 
 #endif /* MBEDTLS_HAVE_TIME */
-    }
+
+exit:
+    if( ret != 0 )
+        mbedtls_ssl_session_free( session );
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= check_identity_match_ticket" ) );
     return( ret );
@@ -247,9 +272,8 @@
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     if( ssl_tls13_offered_psks_check_identity_match_ticket(
-            ssl, (mbedtls_ssl_session *)session,
-            identity, identity_len,
-            obfuscated_ticket_age ) == SSL_TLS1_3_OFFERED_PSK_MATCH )
+            ssl, identity, identity_len, obfuscated_ticket_age,
+            (mbedtls_ssl_session *)session ) == SSL_TLS1_3_OFFERED_PSK_MATCH )
     {
         mbedtls_ssl_session *i_session=(mbedtls_ssl_session *)session;
         ssl->handshake->resume = 1;