Adds Session Ticket TLS Extension handling.

New Session Ticket Handshake Message handling is still needed for Session Tickets to work.
This commit is contained in:
Moisés Guimarães 2014-09-30 09:24:42 -03:00
parent 6a75c8d144
commit a937040087
6 changed files with 237 additions and 31 deletions

View File

@ -1233,7 +1233,7 @@ typedef enum {
MAX_FRAGMENT_LENGTH = 0x0001,
TRUNCATED_HMAC = 0x0004,
ELLIPTIC_CURVES = 0x000a,
/*SESSION_TICKET = 0x0023, not used yet in switch statements */
SESSION_TICKET = 0x0023,
SECURE_RENEGOTIATION = 0xff01
} TLSX_Type;
@ -1317,7 +1317,6 @@ CYASSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions);
typedef struct EllipticCurve {
word16 name; /* CurveNames */
struct EllipticCurve* next; /* List Behavior */
} EllipticCurve;
CYASSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name);
@ -1354,6 +1353,20 @@ CYASSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions);
#endif /* HAVE_SECURE_RENEGOTIATION */
#ifdef HAVE_SESSION_TICKET
typedef struct SessionTicket {
word32 lifetime;
byte* data;
word16 size;
} SessionTicket;
CYASSL_LOCAL int TLSX_UseSessionTicket(TLSX** extensions,
SessionTicket* ticket);
CYASSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
byte* data, word16 size);
CYASSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket);
#endif /* HAVE_SESSION_TICKET */
/* CyaSSL context type */
struct CYASSL_CTX {
@ -2043,6 +2056,23 @@ struct CYASSL {
#ifdef HAVE_SECURE_RENEGOTIATION
SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */
#endif /* user turned on */
#ifdef HAVE_SESSION_TICKET
#ifndef NO_CYASSL_CLIENT
/*
Create cantidate_ticket when processing New Session Ticket Handshake
Message. When the ticket is validated at Finished Handshake Message,
move canditate_ticket to session_ticket and call:
TLSX_UseSessionTicket(&ssl->extensions, ssl->session_ticket);
If the session_ticket must be destroyed, call:
TLSX_UseSessionTicket(&ssl->extensions, NULL);
This function doesn't free an early ticket, but will erase it's
reference inside the extensions.
*/
SessionTicket* candidate_ticket;
SessionTicket* session_ticket;
#endif
#endif
#endif /* HAVE_TLS_EXTENSIONS */
#ifdef HAVE_NETX
NetX_Ctx nxCtx; /* NetX IO Context */

View File

@ -1316,7 +1316,17 @@ CYASSL_API int CyaSSL_CTX_UseSupportedCurve(CYASSL_CTX* ctx,
CYASSL_API int CyaSSL_UseSecureRenegotiation(CYASSL* ssl);
CYASSL_API int CyaSSL_Rehandshake(CYASSL* ssl);
#endif /* HAVE_SECURE_RENEGOTIATION */
#endif
/* Session Ticket */
#ifdef HAVE_SESSION_TICKET
#ifndef NO_CYASSL_CLIENT
CYASSL_API int CyaSSL_UseSessionTicket(CYASSL* ssl);
CYASSL_API int CyaSSL_CTX_UseSessionTicket(CYASSL_CTX* ctx);
#endif
#endif
#define CYASSL_CRL_MONITOR 0x01 /* monitor this dir flag */
#define CYASSL_CRL_START_MON 0x02 /* start monitoring flag */

View File

@ -596,6 +596,10 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
if (CyaSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS)
err_sys("UseTruncatedHMAC failed");
#endif
#ifdef HAVE_SESSION_TICKET
if (CyaSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS)
err_sys("UseSessionTicket failed");
#endif
if (benchmark) {
/* time passed in number of connects give average */

View File

@ -1745,6 +1745,12 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
#ifdef HAVE_SECURE_RENEGOTIATION
ssl->secure_renegotiation = NULL;
#endif
#ifdef HAVE_SESSION_TICKET
#ifndef NO_CYASSL_CLIENT
ssl->candidate_ticket = NULL;
ssl->session_ticket = NULL;
#endif
#endif
#endif
ssl->rng = NULL;
@ -2001,6 +2007,12 @@ void SSL_ResourceFree(CYASSL* ssl)
#ifdef HAVE_TLS_EXTENSIONS
TLSX_FreeAll(ssl->extensions);
#endif
#ifdef HAVE_SESSION_TICKET
#ifndef NO_CYASSL_CLIENT
TLSX_SessionTicket_Free(ssl->candidate_ticket);
TLSX_SessionTicket_Free(ssl->session_ticket);
#endif
#endif
#ifdef HAVE_NETX
if (ssl->nxCtx.nxPacket)
nx_packet_release(ssl->nxCtx.nxPacket);

View File

@ -796,6 +796,26 @@ int CyaSSL_Rehandshake(CYASSL* ssl)
#endif /* HAVE_SECURE_RENEGOTIATION */
/* Session Ticket */
#ifdef HAVE_SESSION_TICKET
#ifndef NO_CYASSL_CLIENT
int CyaSSL_UseSessionTicket(CYASSL* ssl)
{
if (ssl == NULL)
return BAD_FUNC_ARG;
return TLSX_UseSessionTicket(&ssl->extensions, NULL);
}
int CyaSSL_CTX_UseSessionTicket(CYASSL_CTX* ctx)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
return TLSX_UseSessionTicket(&ctx->extensions, NULL);
}
#endif
#endif
#ifndef CYASSL_LEANPSK

186
src/tls.c
View File

@ -1314,20 +1314,6 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl)
#ifdef HAVE_TRUNCATED_HMAC
int TLSX_UseTruncatedHMAC(TLSX** extensions)
{
int ret = 0;
if (extensions == NULL)
return BAD_FUNC_ARG;
if (!TLSX_Find(*extensions, TRUNCATED_HMAC))
if ((ret = TLSX_Push(extensions, TRUNCATED_HMAC, NULL)) != 0)
return ret;
return SSL_SUCCESS;
}
static int TLSX_THM_Parse(CYASSL* ssl, byte* input, word16 length,
byte isRequest)
{
@ -1349,6 +1335,19 @@ static int TLSX_THM_Parse(CYASSL* ssl, byte* input, word16 length,
return 0;
}
int TLSX_UseTruncatedHMAC(TLSX** extensions)
{
int ret = 0;
if (extensions == NULL)
return BAD_FUNC_ARG;
if ((ret = TLSX_Push(extensions, TRUNCATED_HMAC, NULL)) != 0)
return ret;
return SSL_SUCCESS;
}
#define THM_PARSE TLSX_THM_Parse
#else
@ -1637,9 +1636,11 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name)
#define EC_VALIDATE_REQUEST(a, b)
#endif /* HAVE_SUPPORTED_CURVES */
#ifdef HAVE_SECURE_RENEGOTIATION
static byte TLSX_SCR_GetSize(SecureRenegotiation* data, int isRequest)
static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data,
int isRequest)
{
byte length = OPAQUE8_LEN; /* empty info length */
@ -1655,8 +1656,8 @@ static byte TLSX_SCR_GetSize(SecureRenegotiation* data, int isRequest)
return length;
}
static word16 TLSX_SCR_Write(SecureRenegotiation* data, byte* output,
int isRequest)
static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data,
byte* output, int isRequest)
{
word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */
@ -1677,8 +1678,8 @@ static word16 TLSX_SCR_Write(SecureRenegotiation* data, byte* output,
return offset;
}
static int TLSX_SCR_Parse(CYASSL* ssl, byte* input, word16 length,
byte isRequest)
static int TLSX_SecureRenegotiation_Parse(CYASSL* ssl, byte* input,
word16 length, byte isRequest)
{
int ret = SECURE_RENEGOTIATION_E;
@ -1745,9 +1746,9 @@ int TLSX_UseSecureRenegotiation(TLSX** extensions)
#define SCR_FREE_ALL(data) XFREE(data, NULL, DYNAMIC_TYPE_TLSX)
#define SCR_GET_SIZE TLSX_SCR_GetSize
#define SCR_WRITE TLSX_SCR_Write
#define SCR_PARSE TLSX_SCR_Parse
#define SCR_GET_SIZE TLSX_SecureRenegotiation_GetSize
#define SCR_WRITE TLSX_SecureRenegotiation_Write
#define SCR_PARSE TLSX_SecureRenegotiation_Parse
#else
@ -1758,6 +1759,116 @@ int TLSX_UseSecureRenegotiation(TLSX** extensions)
#endif /* HAVE_SECURE_RENEGOTIATION */
#ifdef HAVE_SESSION_TICKET
static void TLSX_SessionTicket_ValidateRequest(CYASSL* ssl)
{
TLSX* extension = TLSX_Find(ssl->extensions, SESSION_TICKET);
SessionTicket* ticket = extension ? extension->data : NULL;
if (ticket) {
/* TODO validate ticket timeout here! */
if (ticket->lifetime == 0xfffffff) {
/* send empty ticket on timeout */
TLSX_UseSessionTicket(&ssl->extensions, NULL);
}
}
}
static byte TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest)
{
return isRequest && ticket ? OPAQUE16_LEN + ticket->size : 0;
}
static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
int isRequest)
{
int offset = 0; /* empty ticket */
if (isRequest && ticket) {
c16toa(ticket->size, output + offset);
offset += OPAQUE16_LEN;
XMEMCPY(output + offset, ticket->data, ticket->size);
offset += ticket->size;
}
return offset;
}
static int TLSX_SessionTicket_Parse(CYASSL* ssl, byte* input, word16 length,
byte isRequest)
{
if (!isRequest)
return length != 0 ? BUFFER_ERROR : 0;
/* TODO server side */
(void)ssl;
(void)input;
return 0;
}
CYASSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
byte* data, word16 size)
{
SessionTicket* ticket = (SessionTicket*)XMALLOC(sizeof(SessionTicket),
NULL, DYNAMIC_TYPE_TLSX);
if (ticket) {
ticket->data = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TLSX);
if (ticket->data == NULL) {
XFREE(ticket, NULL, DYNAMIC_TYPE_TLSX);
return NULL;
}
XMEMCPY(ticket->data, data, size);
ticket->size = size;
ticket->lifetime = lifetime;
}
return ticket;
}
CYASSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket)
{
if (ticket) {
XFREE(ticket->data, NULL, DYNAMIC_TYPE_TLSX);
XFREE(ticket, NULL, DYNAMIC_TYPE_TLSX);
}
}
int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket)
{
int ret = 0;
if (extensions == NULL)
return BAD_FUNC_ARG;
/* If the ticket is NULL, the client will request a new ticket from the
server. Otherwise, the client will use it in the next client hello. */
if ((ret = TLSX_Push(extensions, SESSION_TICKET, (void*)ticket)) != 0)
return ret;
return SSL_SUCCESS;
}
#define STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest
#define STK_GET_SIZE TLSX_SessionTicket_GetSize
#define STK_WRITE TLSX_SessionTicket_Write
#define STK_PARSE TLSX_SessionTicket_Parse
#else
#define STK_VALIDATE_REQUEST(a)
#define STK_GET_SIZE(a, b) 0
#define STK_WRITE(a, b, c) 0
#define STK_PARSE(a, b, c, d) 0
#endif /* HAVE_SESSION_TICKET */
TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
{
TLSX* extension = list;
@ -1795,6 +1906,10 @@ void TLSX_FreeAll(TLSX* list)
case SECURE_RENEGOTIATION:
SCR_FREE_ALL(extension->data);
break;
case SESSION_TICKET:
/* Nothing to do. */
break;
}
XFREE(extension, 0, DYNAMIC_TYPE_TLSX);
@ -1842,6 +1957,10 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest)
case SECURE_RENEGOTIATION:
length += SCR_GET_SIZE(extension->data, isRequest);
break;
case SESSION_TICKET:
length += STK_GET_SIZE(extension->data, isRequest);
break;
}
TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
@ -1875,11 +1994,11 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
switch (extension->type) {
case SERVER_NAME_INDICATION:
if (isRequest)
offset += SNI_WRITE((SNI*)extension->data, output + offset);
offset += SNI_WRITE(extension->data, output + offset);
break;
case MAX_FRAGMENT_LENGTH:
offset += MFL_WRITE((byte*)extension->data, output + offset);
offset += MFL_WRITE(extension->data, output + offset);
break;
case TRUNCATED_HMAC:
@ -1887,13 +2006,17 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
break;
case ELLIPTIC_CURVES:
offset += EC_WRITE((EllipticCurve*)extension->data,
output + offset);
offset += EC_WRITE(extension->data, output + offset);
break;
case SECURE_RENEGOTIATION:
offset += SCR_WRITE((SecureRenegotiation*)extension->data,
output + offset, isRequest);
offset += SCR_WRITE(extension->data, output + offset,
isRequest);
break;
case SESSION_TICKET:
offset += STK_WRITE(extension->data, output + offset,
isRequest);
break;
}
@ -1916,6 +2039,7 @@ word16 TLSX_GetRequestSize(CYASSL* ssl)
byte semaphore[SEMAPHORE_SIZE] = {0};
EC_VALIDATE_REQUEST(ssl, semaphore);
STK_VALIDATE_REQUEST(ssl);
if (ssl->extensions)
length += TLSX_GetSize(ssl->extensions, semaphore, 1);
@ -2075,6 +2199,12 @@ int TLSX_Parse(CYASSL* ssl, byte* input, word16 length, byte isRequest,
ret = SCR_PARSE(ssl, input + offset, size, isRequest);
break;
case SESSION_TICKET:
CYASSL_MSG("Session Ticket extension received");
ret = STK_PARSE(ssl, input + offset, size, isRequest);
break;
case HELLO_EXT_SIG_ALGO:
if (isRequest) {
/* do not mess with offset inside the switch! */