diff --git a/README b/README index c9f11555f..1acb7a1d5 100644 --- a/README +++ b/README @@ -34,10 +34,11 @@ before calling SSL_new(); Though it's not recommended. *** end Notes *** -CyaSSL intermediate Release 3.2.1c (9/30/2014) +CyaSSL intermediate Release 3.2.2 (10/13/2014) - Small stack improvements for at TLS/SSL layer - Adds client side Secure Renegotiation, * not recommended * +- Client side session ticket support, not fully tested with Secure Renegotiation The CyaSSL manual is available at: http://www.wolfssl.com/documentation/CyaSSL-Manual.pdf. For build instructions diff --git a/configure.ac b/configure.ac index c2a0499d7..e07ff1819 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ # # -AC_INIT([cyassl],[3.2.1c],[https://github.com/cyassl/cyassl/issues],[cyassl],[http://www.wolfssl.com]) +AC_INIT([cyassl],[3.2.2],[https://github.com/cyassl/cyassl/issues],[cyassl],[http://www.wolfssl.com]) AC_CONFIG_AUX_DIR([build-aux]) diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index a2b7e477d..20d816264 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -424,6 +424,8 @@ CYASSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, word32 i = *inOutIdx; byte b; + *len = 0; /* default length */ + if ( (i+1) > maxIdx) { /* for first read */ CYASSL_MSG("GetLength bad index on input"); return BUFFER_E; @@ -452,7 +454,8 @@ CYASSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, } *inOutIdx = i; - *len = length; + if (length > 0) + *len = length; return length; } diff --git a/cyassl/error-ssl.h b/cyassl/error-ssl.h index 625cd8296..7b7befcbd 100644 --- a/cyassl/error-ssl.h +++ b/cyassl/error-ssl.h @@ -119,16 +119,19 @@ enum CyaSSL_ErrorCodes { EXTKEYUSE_AUTH_E = -386, /* ExtKeyUse server|client_auth */ SEND_OOB_READ_E = -387, /* Send Cb out of bounds read */ SECURE_RENEGOTIATION_E = -388, /* Invalid Renegotiation Info */ + SESSION_TICKET_LEN_E = -389, /* Session Ticket too large */ + SESSION_TICKET_EXPECT_E = -390, /* Session Ticket missing */ + SCR_DIFFERENT_CERT_E = -391, /* SCR Different cert error */ + /* add strings to SetErrorString !!!!! */ /* begin negotiation parameter errors */ - UNSUPPORTED_SUITE = -390, /* unsupported cipher suite */ - MATCH_SUITE_ERROR = -391, /* can't match cipher suite */ + UNSUPPORTED_SUITE = -500, /* unsupported cipher suite */ + MATCH_SUITE_ERROR = -501, /* 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 */ - SESSION_TICKET_EXPECT_E = -393 /* Session Ticket missing */ + /* no error stings go down here, add above negotiation errors !!!! */ }; diff --git a/cyassl/internal.h b/cyassl/internal.h index 29bf6dbd1..669a386a5 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -649,7 +649,7 @@ enum Misc { MAX_COMP_EXTRA = 1024, /* max compression extra */ MAX_MTU = 1500, /* max expected MTU */ MAX_UDP_SIZE = 8192 - 100, /* was MAX_MTU - 100 */ - MAX_DH_SZ = 612, /* 2240 p, pub, g + 2 byte size for each */ + MAX_DH_SZ = 1036, /* 4096 p, pub, g + 2 byte size for each */ MAX_STR_VERSION = 8, /* string rep of protocol version */ PAD_MD5 = 48, /* pad length for finished */ @@ -1352,6 +1352,7 @@ typedef struct SecureRenegotiation { enum key_cache_state cache_status; /* track key cache state */ byte client_verify_data[TLS_FINISHED_SZ]; /* cached */ byte server_verify_data[TLS_FINISHED_SZ]; /* cached */ + byte subject_hash[SHA_DIGEST_SIZE]; /* peer cert hash */ Keys tmp_keys; /* can't overwrite real keys yet */ } SecureRenegotiation; @@ -1644,6 +1645,7 @@ struct CYASSL_X509_CHAIN { /* CyaSSL session type */ struct CYASSL_SESSION { byte sessionID[ID_LEN]; /* id for protocol */ + byte sessionIDSz; byte masterSecret[SECRET_LEN]; /* stored secret */ word32 bornOn; /* create time in seconds */ word32 timeout; /* timeout in seconds */ @@ -1803,6 +1805,7 @@ typedef struct Arrays { byte clientRandom[RAN_LEN]; byte serverRandom[RAN_LEN]; byte sessionID[ID_LEN]; + byte sessionIDSz; byte preMasterSecret[ENCRYPT_LEN]; byte masterSecret[SECRET_LEN]; #ifdef CYASSL_DTLS diff --git a/cyassl/version.h b/cyassl/version.h index 074c3a898..70cd7a129 100644 --- a/cyassl/version.h +++ b/cyassl/version.h @@ -26,8 +26,8 @@ extern "C" { #endif -#define LIBCYASSL_VERSION_STRING "3.2.1c" -#define LIBCYASSL_VERSION_HEX 0x03002001 +#define LIBCYASSL_VERSION_STRING "3.2.2" +#define LIBCYASSL_VERSION_HEX 0x03002002 #ifdef __cplusplus } diff --git a/src/internal.c b/src/internal.c index fdb255fb1..896cb531b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1806,7 +1806,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) /* arrays */ ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap, - DYNAMIC_TYPE_ARRAYS); + DYNAMIC_TYPE_ARRAYS); if (ssl->arrays == NULL) { CYASSL_MSG("Arrays Memory error"); return MEMORY_E; @@ -1919,6 +1919,7 @@ void FreeArrays(CYASSL* ssl, int keep) if (ssl->arrays && keep) { /* keeps session id for user retrieval */ XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); + ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; } XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS); ssl->arrays = NULL; @@ -4114,6 +4115,29 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx, } } +#ifdef HAVE_SECURE_RENEGOTIATION + if (fatal == 0 && ssl->secure_renegotiation + && ssl->secure_renegotiation->enabled) { + + if (ssl->keys.encryptionOn) { + /* compare against previous time */ + if (XMEMCMP(dCert.subjectHash, + ssl->secure_renegotiation->subject_hash, + SHA_DIGEST_SIZE) != 0) { + CYASSL_MSG("Peer sent different cert during scr, fatal"); + fatal = 1; + ret = SCR_DIFFERENT_CERT_E; + } + } + + /* cache peer's hash */ + if (fatal == 0) { + XMEMCPY(ssl->secure_renegotiation->subject_hash, + dCert.subjectHash, SHA_DIGEST_SIZE); + } + } +#endif + #ifdef HAVE_OCSP if (fatal == 0 && ssl->ctx->cm->ocspEnabled) { ret = CheckCertOCSP(ssl->ctx->cm->ocsp, &dCert); @@ -7676,13 +7700,14 @@ const char* CyaSSL_ERR_reason_error_string(unsigned long e) case SECURE_RENEGOTIATION_E: return "Invalid Renegotiation Error"; -#ifdef HAVE_SESSION_TICKET case SESSION_TICKET_LEN_E: return "Session Ticket Too Long Error"; case SESSION_TICKET_EXPECT_E: return "Session Ticket Error"; -#endif + + case SCR_DIFFERENT_CERT_E: + return "Peer sent different cert during SCR"; default : return "unknown error number"; @@ -8745,7 +8770,9 @@ static void PickHashSigAlgo(CYASSL* ssl, byte *output; word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; int sendSz; - int idSz = ssl->options.resuming ? ID_LEN : 0; + int idSz = ssl->options.resuming + ? ssl->session.sessionIDSz + : 0; int ret; if (ssl->suites == NULL) { @@ -8754,7 +8781,7 @@ static void PickHashSigAlgo(CYASSL* ssl, } #ifdef HAVE_SESSION_TICKET - if (ssl->session.ticketLen > 0) { + if (ssl->options.resuming && ssl->session.ticketLen > 0) { SessionTicket* ticket; ticket = TLSX_SessionTicket_Create(0, @@ -8828,8 +8855,9 @@ static void PickHashSigAlgo(CYASSL* ssl, /* then session id */ output[idx++] = (byte)idSz; if (idSz) { - XMEMCPY(output + idx, ssl->session.sessionID, ID_LEN); - idx += ID_LEN; + XMEMCPY(output + idx, ssl->session.sessionID, + ssl->session.sessionIDSz); + idx += ssl->session.sessionIDSz; } /* then DTLS cookie */ @@ -8987,7 +9015,6 @@ static void PickHashSigAlgo(CYASSL* ssl, static int DoServerHello(CYASSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz) { - byte b; byte cs0; /* cipher suite bytes 0, 1 */ byte cs1; ProtocolVersion pv; @@ -9053,20 +9080,23 @@ static void PickHashSigAlgo(CYASSL* ssl, i += RAN_LEN; /* session id */ - b = input[i++]; + ssl->arrays->sessionIDSz = input[i++]; - if (b == ID_LEN) { - if ((i - begin) + ID_LEN > helloSz) + if (ssl->arrays->sessionIDSz > ID_LEN) { + CYASSL_MSG("Invalid session ID size"); + ssl->arrays->sessionIDSz = 0; + return BUFFER_ERROR; + } + else if (ssl->arrays->sessionIDSz) { + if ((i - begin) + ssl->arrays->sessionIDSz > helloSz) return BUFFER_ERROR; - XMEMCPY(ssl->arrays->sessionID, input + i, min(b, ID_LEN)); - i += ID_LEN; + XMEMCPY(ssl->arrays->sessionID, input + i, + ssl->arrays->sessionIDSz); + i += ssl->arrays->sessionIDSz; ssl->options.haveSessionId = 1; } - else if (b) { - CYASSL_MSG("Invalid session ID size"); - return BUFFER_ERROR; /* session ID nor 0 neither 32 bytes long */ - } + /* suite and compression */ if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz) diff --git a/src/ssl.c b/src/ssl.c index 276bb910c..a780fdab8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -736,7 +736,7 @@ int CyaSSL_UseSecureRenegotiation(CYASSL* ssl) } -/* do a secure renegotiation handshake, use forced, we discourage */ +/* do a secure renegotiation handshake, user forced, we discourage */ int CyaSSL_Rehandshake(CYASSL* ssl) { int ret; @@ -759,6 +759,15 @@ int CyaSSL_Rehandshake(CYASSL* ssl) return SECURE_RENEGOTIATION_E; } +#ifndef NO_FORCE_SCR_SAME_SUITE + /* force same suite */ + if (ssl->suites) { + ssl->suites->suiteSz = SUITE_LEN; + ssl->suites->suites[0] = ssl->options.cipherSuite0; + ssl->suites->suites[1] = ssl->options.cipherSuite; + } +#endif + /* reset handshake states */ ssl->options.serverState = NULL_STATE; ssl->options.clientState = NULL_STATE; @@ -5640,6 +5649,7 @@ int AddSession(CYASSL* ssl) ssl->arrays->masterSecret, SECRET_LEN); XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays->sessionID, ID_LEN); + SessionCache[row].Sessions[idx].sessionIDSz = ssl->arrays->sessionIDSz; SessionCache[row].Sessions[idx].timeout = ssl->timeout; SessionCache[row].Sessions[idx].bornOn = LowResTimer(); diff --git a/src/tls.c b/src/tls.c index ab3ce0bf6..93e8dcf32 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1776,7 +1776,7 @@ static void TLSX_SessionTicket_ValidateRequest(CYASSL* ssl) } -static byte TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) +static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) { return isRequest && ticket ? ticket->size : 0; }