Parse NewSessionTicket message
diff --git a/include/polarssl/error.h b/include/polarssl/error.h
index f8c23e6..48de009 100644
--- a/include/polarssl/error.h
+++ b/include/polarssl/error.h
@@ -84,7 +84,7 @@
* ECP 4 4 (Started from top)
* MD 5 4
* CIPHER 6 5
- * SSL 6 2 (Started from top)
+ * SSL 6 4 (Started from top)
* SSL 7 31
*
* Module dependent error code (5 bits 0x.08.-0x.F8.)
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 48263e5..6d00c9d 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -107,6 +107,8 @@
#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */
#define POLARSSL_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */
#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */
+#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */
+
/*
* Various constants
@@ -239,6 +241,7 @@
#define SSL_HS_HELLO_REQUEST 0
#define SSL_HS_CLIENT_HELLO 1
#define SSL_HS_SERVER_HELLO 2
+#define SSL_HS_NEW_SESSION_TICKET 4
#define SSL_HS_CERTIFICATE 11
#define SSL_HS_SERVER_KEY_EXCHANGE 12
#define SSL_HS_CERTIFICATE_REQUEST 13
@@ -313,7 +316,8 @@
SSL_SERVER_FINISHED,
SSL_FLUSH_BUFFERS,
SSL_HANDSHAKE_WRAPUP,
- SSL_HANDSHAKE_OVER
+ SSL_HANDSHAKE_OVER,
+ SSL_SERVER_NEW_SESSION_TICKET,
}
ssl_states;
@@ -342,6 +346,7 @@
unsigned char *ticket; /*!< RFC 5077 session ticket */
size_t ticket_len; /*!< session ticket length */
+ uint32_t ticket_lifetime; /*!< ticket lifetime hint */
unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */
int trunc_hmac; /*!< flag for truncated hmac activation */
@@ -433,6 +438,8 @@
int resume; /*!< session resume indicator*/
int max_major_ver; /*!< max. major version client*/
int max_minor_ver; /*!< max. minor version client*/
+
+ int new_session_ticket; /*!< use NewSessionTicket? */
};
struct _ssl_context
diff --git a/library/error.c b/library/error.c
index 560c54c..94d8dc1 100644
--- a/library/error.c
+++ b/library/error.c
@@ -369,6 +369,8 @@
snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" );
if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION) )
snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) )
+ snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" );
#endif /* POLARSSL_SSL_TLS_C */
#if defined(POLARSSL_X509_PARSE_C)
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 9b64c9a..f572cab 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -30,6 +30,13 @@
#include "polarssl/debug.h"
#include "polarssl/ssl.h"
+#if defined(POLARSSL_MEMORY_C)
+#include "polarssl/memory.h"
+#else
+#define polarssl_malloc malloc
+#define polarssl_free free
+#endif
+
#include <stdlib.h>
#include <stdio.h>
@@ -627,7 +634,8 @@
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
((void) buf);
- ((void) ssl);
+
+ ssl->handshake->new_session_ticket = 1;
return( 0 );
}
@@ -1890,6 +1898,97 @@
!POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED &&
!POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+static int ssl_parse_new_session_ticket( ssl_context *ssl )
+{
+ int ret;
+ uint32_t lifetime;
+ size_t ticket_len;
+ unsigned char *ticket;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) );
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ /*
+ * struct {
+ * uint32 ticket_lifetime_hint;
+ * opaque ticket<0..2^16-1>;
+ * } NewSessionTicket;
+ *
+ * 0 . 0 handshake message type
+ * 1 . 3 handshake message length
+ * 4 . 7 ticket_lifetime_hint
+ * 8 . 9 ticket_len (n)
+ * 10 . 9+n ticket content
+ */
+ if( ssl->in_msg[0] != SSL_HS_NEW_SESSION_TICKET ||
+ ssl->in_hslen < 10 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
+ }
+
+ lifetime = ( ssl->in_msg[4] << 24 ) | ( ssl->in_msg[5] << 16 ) |
+ ( ssl->in_msg[6] << 8 ) | ( ssl->in_msg[7] );
+
+ ticket_len = ( ssl->in_msg[8] << 8 ) | ( ssl->in_msg[9] );
+
+ if( ticket_len + 10 != ssl->in_hslen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
+ }
+
+ ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+ SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) );
+
+ /*
+ * Zero-length ticket means the server changed his mind and doesn't want
+ * to send a ticket after all, so just forget it
+ */
+ if( ticket_len == 0)
+ return( 0 );
+
+ polarssl_free( ssl->session_negotiate->ticket );
+ ssl->session_negotiate->ticket = NULL;
+ ssl->session_negotiate->ticket_len = 0;
+
+ if( ( ticket = polarssl_malloc( ticket_len ) ) == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "ticket malloc failed" ) );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ memcpy( ticket, ssl->in_msg + 10, ticket_len );
+
+ ssl->session_negotiate->ticket = ticket;
+ ssl->session_negotiate->ticket_len = ticket_len;
+ ssl->session_negotiate->ticket_lifetime = lifetime;
+
+ /*
+ * RFC 5077 section 3.4:
+ * "If the client receives a session ticket from the server, then it
+ * discards any Session ID that was sent in the ServerHello."
+ */
+ SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) );
+ ssl->session_negotiate->length = 0;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) );
+
+ return( 0 );
+}
+
/*
* SSL handshake -- client side -- single step
*/
@@ -1973,9 +2072,14 @@
break;
/*
- * <== ChangeCipherSpec
+ * <== ( NewSessionTicket )
+ * ChangeCipherSpec
* Finished
*/
+ case SSL_SERVER_NEW_SESSION_TICKET:
+ ret = ssl_parse_new_session_ticket( ssl );
+ break;
+
case SSL_SERVER_CHANGE_CIPHER_SPEC:
ret = ssl_parse_change_cipher_spec( ssl );
break;
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 7e8ff34..bf45ec8 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2619,6 +2619,11 @@
else
ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
}
+ else if( ssl->endpoint == SSL_IS_CLIENT &&
+ ssl->handshake->new_session_ticket != 0 )
+ {
+ ssl->state = SSL_SERVER_NEW_SESSION_TICKET;
+ }
else
ssl->state++;