From 9dbc1d2d00f5e2ec8997b84c5e00ddb496bc3317 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 1 Oct 2014 16:28:01 -0700 Subject: [PATCH] Parse the NewSessionTicket handshake message --- cyassl/error-ssl.h | 4 +++- cyassl/internal.h | 8 +++++++ src/internal.c | 59 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/cyassl/error-ssl.h b/cyassl/error-ssl.h index 40c6c0c8d..f8c7f8ac2 100644 --- a/cyassl/error-ssl.h +++ b/cyassl/error-ssl.h @@ -123,9 +123,11 @@ enum CyaSSL_ErrorCodes { /* begin negotiation parameter errors */ UNSUPPORTED_SUITE = -390, /* unsupported cipher suite */ - MATCH_SUITE_ERROR = -391 /* can't match cipher suite */ + MATCH_SUITE_ERROR = -391, /* can't match cipher suite */ /* end negotiation parameter errors only 10 for now */ /* add strings to SetErrorString !!!!! */ + + SESSION_TICKET_LEN_E = -392 /* Session Ticket too large */ }; diff --git a/cyassl/internal.h b/cyassl/internal.h index 295d8e6b0..6ce3ab68e 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -681,9 +681,11 @@ enum Misc { OPAQUE8_LEN = 1, /* 1 byte */ OPAQUE16_LEN = 2, /* 2 bytes */ OPAQUE24_LEN = 3, /* 3 bytes */ + OPAQUE32_LEN = 4, /* 4 bytes */ COMP_LEN = 1, /* compression length */ CURVE_LEN = 2, /* ecc named curve length */ SERVER_ID_LEN = 20, /* server session id length */ + SESSION_TICKET_LEN = 256, /* Session ticket length */ HANDSHAKE_HEADER_SZ = 4, /* type + length(3) */ RECORD_HEADER_SZ = 5, /* type + version + len(2) */ @@ -1652,6 +1654,12 @@ struct CYASSL_SESSION { byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ word16 idLen; /* serverID length */ #endif +#ifdef HAVE_SESSION_TICKET + word32 ticketBornOn; /* create time in seconds */ + word32 ticketTimeout; /* timeout in seconds */ + byte ticket[SESSION_TICKET_LEN]; + word16 ticketLen; +#endif }; diff --git a/src/internal.c b/src/internal.c index 2addac837..02faec4d2 100644 --- a/src/internal.c +++ b/src/internal.c @@ -76,6 +76,10 @@ static int BuildMessage(CYASSL* ssl, byte* output, int outSz, static int DoCertificateRequest(CYASSL* ssl, const byte* input, word32*, word32); #endif + #ifdef HAVE_SESSION_TICKET + static int DoSessionTicket(CYASSL* ssl, const byte* input, word32*, + word32); + #endif #endif @@ -232,7 +236,7 @@ static INLINE void ato16(const byte* c, word16* u16) } -#ifdef CYASSL_DTLS +#if defined(CYASSL_DTLS) || defined(HAVE_SESSION_TICKET) /* convert opaque to 32 bit integer */ static INLINE void ato32(const byte* c, word32* u32) @@ -4590,6 +4594,13 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx, CYASSL_MSG("processing server key exchange"); ret = DoServerKeyExchange(ssl, input, inOutIdx, size); break; + +#ifdef HAVE_SESSION_TICKET + case session_ticket: + CYASSL_MSG("processing session ticket"); + ret = DoSessionTicket(ssl, input, inOutIdx, size); + break; +#endif /* HAVE_SESSION_TICKET */ #endif #ifndef NO_CERTS @@ -7648,6 +7659,9 @@ const char* CyaSSL_ERR_reason_error_string(unsigned long e) case SECURE_RENEGOTIATION_E: return "Invalid Renegotiation Error"; + case SESSION_TICKET_LEN_E: + return "Session Ticket Too Long Error"; + default : return "unknown error number"; } @@ -10375,6 +10389,49 @@ static void PickHashSigAlgo(CYASSL* ssl, #endif /* NO_CERTS */ +#ifdef HAVE_SESSION_TICKET +int DoSessionTicket(CYASSL* ssl, + const byte* input, word32* inOutIdx, word32 size) +{ + word32 begin = *inOutIdx; + word32 lifetime; + word16 length; + + if ((*inOutIdx - begin) + OPAQUE32_LEN > size) + return BUFFER_ERROR; + + ato32(input + *inOutIdx, &lifetime); + *inOutIdx += OPAQUE32_LEN; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if (length > sizeof(ssl->session.ticket)) + return SESSION_TICKET_LEN_E; + + if ((*inOutIdx - begin) + length > size) + return BUFFER_ERROR; + + if (length > 0) { + XMEMCPY(ssl->session.ticket, input + *inOutIdx, length); + *inOutIdx += length; + ssl->session.ticketLen = length; + ssl->session.ticketTimeout = lifetime; + ssl->session.ticketBornOn = LowResTimer(); + } + else { + ssl->session.ticketLen = 0; + ssl->session.ticketTimeout = 0; + ssl->session.ticketBornOn = 0; + } + + return BuildFinished(ssl, &ssl->verifyHashes, server); +} +#endif /* HAVE_SESSION_TICKET */ + #endif /* NO_CYASSL_CLIENT */