diff --git a/Makefile.am b/Makefile.am index d2a99cfae..48a5621e1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -77,9 +77,10 @@ include testsuite/include.am include tests/include.am include sslSniffer/sslSnifferTest/include.am include rpm/include.am -include mqx/wolfcrypt_test/Sources/include.am +# TODO: fix, this commented out mqx ones have spaces in file names +#include mqx/wolfcrypt_test/Sources/include.am include mqx/cyassl/include.am -include mqx/cyassl_client/Sources/include.am +#include mqx/cyassl_client/Sources/include.am include mqx/util_lib/Sources/include.am include mplabx/include.am include mplabx/ctaocrypt_benchmark.X/nbproject/include.am diff --git a/configure.ac b/configure.ac index a829be7dc..af2256e79 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ # # -AC_INIT([cyassl],[3.2.0],[https://github.com/cyassl/cyassl/issues],[cyassl],[http://www.wolfssl.com]) +AC_INIT([cyassl],[3.2.1b],[https://github.com/cyassl/cyassl/issues],[cyassl],[http://www.wolfssl.com]) AC_CONFIG_AUX_DIR([build-aux]) diff --git a/cyassl/internal.h b/cyassl/internal.h index 8db696371..8dd854b52 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1165,6 +1165,66 @@ typedef struct CYASSL_DTLS_CTX { int fd; } CYASSL_DTLS_CTX; + +#ifdef CYASSL_DTLS + + #ifdef WORD64_AVAILABLE + typedef word64 DtlsSeq; + #else + typedef word32 DtlsSeq; + #endif + #define DTLS_SEQ_BITS (sizeof(DtlsSeq) * CHAR_BIT) + + typedef struct DtlsState { + DtlsSeq window; /* Sliding window for current epoch */ + word16 nextEpoch; /* Expected epoch in next record */ + word32 nextSeq; /* Expected sequence in next record */ + + word16 curEpoch; /* Received epoch in current record */ + word32 curSeq; /* Received sequence in current record */ + + DtlsSeq prevWindow; /* Sliding window for old epoch */ + word32 prevSeq; /* Next sequence in allowed old epoch */ + } DtlsState; + +#endif /* CYASSL_DTLS */ + + +/* keys and secrets */ +typedef struct Keys { + byte client_write_MAC_secret[MAX_DIGEST_SIZE]; /* max sizes */ + byte server_write_MAC_secret[MAX_DIGEST_SIZE]; + byte client_write_key[AES_256_KEY_SIZE]; /* max sizes */ + byte server_write_key[AES_256_KEY_SIZE]; + byte client_write_IV[AES_IV_SIZE]; /* max sizes */ + byte server_write_IV[AES_IV_SIZE]; +#ifdef HAVE_AEAD + byte aead_exp_IV[AEAD_EXP_IV_SZ]; + byte aead_enc_imp_IV[AEAD_IMP_IV_SZ]; + byte aead_dec_imp_IV[AEAD_IMP_IV_SZ]; +#endif + + word32 peer_sequence_number; + word32 sequence_number; + +#ifdef CYASSL_DTLS + DtlsState dtls_state; /* Peer's state */ + word16 dtls_peer_handshake_number; + word16 dtls_expected_peer_handshake_number; + + word16 dtls_epoch; /* Current tx epoch */ + word32 dtls_sequence_number; /* Current tx sequence */ + word16 dtls_handshake_number; /* Current tx handshake seq */ +#endif + + word32 encryptSz; /* last size of encrypted data */ + word32 padSz; /* how much to advance after decrypt part */ + byte encryptionOn; /* true after change cipher spec */ + byte decryptedCur; /* only decrypt current record once */ +} Keys; + + + /* RFC 6066 TLS Extensions */ #ifdef HAVE_TLS_EXTENSIONS @@ -1260,11 +1320,22 @@ CYASSL_LOCAL int TLSX_ValidateEllipticCurves(CYASSL* ssl, byte first, #ifdef HAVE_SECURE_RENEGOTIATION +enum key_cache_state { + SCR_CACHE_NULL = 0, /* empty / begin state */ + SCR_CACHE_NEEDED, /* need to cache keys */ + SCR_CACHE_COPY, /* we have a cached copy */ + SCR_CACHE_PARTIAL, /* partial restore to real keys */ + SCR_CACHE_COMPLETE /* complete restore to real keys */ +}; + + /* Additional Conection State according to rfc5746 section 3.1 */ typedef struct SecureRenegotiation { - byte enabled; /* secure_renegotiation flag from rfc */ - byte client_verify_data[TLS_FINISHED_SZ]; - byte server_verify_data[TLS_FINISHED_SZ]; + byte enabled; /* secure_renegotiation flag in rfc */ + 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 */ + Keys tmp_keys; /* can't overwrite real keys yet */ } SecureRenegotiation; CYASSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions); @@ -1464,62 +1535,8 @@ enum ClientCertificateType { enum CipherType { stream, block, aead }; -#ifdef CYASSL_DTLS - - #ifdef WORD64_AVAILABLE - typedef word64 DtlsSeq; - #else - typedef word32 DtlsSeq; - #endif - #define DTLS_SEQ_BITS (sizeof(DtlsSeq) * CHAR_BIT) - - typedef struct DtlsState { - DtlsSeq window; /* Sliding window for current epoch */ - word16 nextEpoch; /* Expected epoch in next record */ - word32 nextSeq; /* Expected sequence in next record */ - - word16 curEpoch; /* Received epoch in current record */ - word32 curSeq; /* Received sequence in current record */ - - DtlsSeq prevWindow; /* Sliding window for old epoch */ - word32 prevSeq; /* Next sequence in allowed old epoch */ - } DtlsState; - -#endif /* CYASSL_DTLS */ -/* keys and secrets */ -typedef struct Keys { - byte client_write_MAC_secret[MAX_DIGEST_SIZE]; /* max sizes */ - byte server_write_MAC_secret[MAX_DIGEST_SIZE]; - byte client_write_key[AES_256_KEY_SIZE]; /* max sizes */ - byte server_write_key[AES_256_KEY_SIZE]; - byte client_write_IV[AES_IV_SIZE]; /* max sizes */ - byte server_write_IV[AES_IV_SIZE]; -#ifdef HAVE_AEAD - byte aead_exp_IV[AEAD_EXP_IV_SZ]; - byte aead_enc_imp_IV[AEAD_IMP_IV_SZ]; - byte aead_dec_imp_IV[AEAD_IMP_IV_SZ]; -#endif - - word32 peer_sequence_number; - word32 sequence_number; - -#ifdef CYASSL_DTLS - DtlsState dtls_state; /* Peer's state */ - word16 dtls_peer_handshake_number; - word16 dtls_expected_peer_handshake_number; - - word16 dtls_epoch; /* Current tx epoch */ - word32 dtls_sequence_number; /* Current tx sequence */ - word16 dtls_handshake_number; /* Current tx handshake seq */ -#endif - - word32 encryptSz; /* last size of encrypted data */ - word32 padSz; /* how much to advance after decrypt part */ - byte encryptionOn; /* true after change cipher spec */ - byte decryptedCur; /* only decrypt current record once */ -} Keys; /* cipher for now */ @@ -2002,8 +2019,8 @@ struct CYASSL { byte truncated_hmac; #endif #ifdef HAVE_SECURE_RENEGOTIATION - SecureRenegotiation* secure_renegotiation; - #endif + SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */ + #endif /* user turned on */ #endif /* HAVE_TLS_EXTENSIONS */ #ifdef HAVE_NETX NetX_Ctx nxCtx; /* NetX IO Context */ diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 4209d0317..6416d5678 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -1312,12 +1312,11 @@ CYASSL_API int CyaSSL_CTX_UseSupportedCurve(CYASSL_CTX* ctx, /* Secure Renegotiation */ #ifdef HAVE_SECURE_RENEGOTIATION -#ifndef NO_CYASSL_CLIENT CYASSL_API int CyaSSL_UseSecureRenegotiation(CYASSL* ssl); +CYASSL_API int CyaSSL_Rehandshake(CYASSL* ssl); -#endif -#endif +#endif /* HAVE_SECURE_RENEGOTIATION */ #define CYASSL_CRL_MONITOR 0x01 /* monitor this dir flag */ #define CYASSL_CRL_START_MON 0x02 /* start monitoring flag */ diff --git a/cyassl/version.h b/cyassl/version.h index 57791007f..f230428d4 100644 --- a/cyassl/version.h +++ b/cyassl/version.h @@ -26,8 +26,8 @@ extern "C" { #endif -#define LIBCYASSL_VERSION_STRING "3.2.0" -#define LIBCYASSL_VERSION_HEX 0x03002000 +#define LIBCYASSL_VERSION_STRING "3.2.1b" +#define LIBCYASSL_VERSION_HEX 0x03002001 #ifdef __cplusplus } diff --git a/examples/client/client.c b/examples/client/client.c index a9dc7dcdc..afe1f5ef1 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -135,6 +135,9 @@ static void Usage(void) printf("-m Match domain name in cert\n"); printf("-N Use Non-blocking sockets\n"); printf("-r Resume session\n"); +#ifdef HAVE_SECURE_RENEGOTIATION + printf("-R Secure Renegotiation\n"); +#endif printf("-f Fewer packets/group messages\n"); printf("-x Disable client cert/key loading\n"); #ifdef SHOW_SIZES @@ -193,6 +196,7 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args) int doPeerCheck = 1; int nonBlocking = 0; int resumeSession = 0; + int scr = 0; /* secure renegotiation */ int trackMemory = 0; int useClientCert = 1; int fewerPackets = 0; @@ -236,11 +240,12 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args) (void)trackMemory; (void)atomicUser; (void)pkCallbacks; + (void)scr; StackTrap(); while ((ch = mygetopt(argc, argv, - "?gdDusmNrtfxUPh:p:v:l:A:c:k:b:zS:L:ToO:")) != -1) { + "?gdDusmNrRtfxUPh:p:v:l:A:c:k:b:zS:L:ToO:")) != -1) { switch (ch) { case '?' : Usage(); @@ -349,6 +354,12 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args) resumeSession = 1; break; + case 'R' : + #ifdef HAVE_SECURE_RENEGOTIATION + scr = 1; + #endif + break; + case 'z' : #ifndef CYASSL_LEANPSK CyaSSL_GetObjectSize(); @@ -640,6 +651,12 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args) if (CyaSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS) err_sys("can't set crl callback"); #endif +#ifdef HAVE_SECURE_RENEGOTIATION + if (scr) { + if (CyaSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) + err_sys("can't enable secure renegotiation"); + } +#endif #ifdef ATOMIC_USER if (atomicUser) SetupAtomicUser(ctx, ssl); @@ -672,6 +689,22 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args) #endif showPeer(ssl); +#ifdef HAVE_SECURE_RENEGOTIATION + if (scr) { + if (nonBlocking) { + printf("not doing secure renegotiation on example with" + " nonblocking yet"); + } + else if (CyaSSL_Rehandshake(ssl) != SSL_SUCCESS) { + int err = CyaSSL_get_error(ssl, 0); + char buffer[CYASSL_MAX_ERROR_SZ]; + printf("err = %d, %s\n", err, + CyaSSL_ERR_error_string(err, buffer)); + err_sys("CyaSSL_Rehandshake failed"); + } + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + if (sendGET) { printf("SSL connect ok, sending GET...\n"); msgSz = 28; diff --git a/src/internal.c b/src/internal.c index 0ce53c297..29e830130 100644 --- a/src/internal.c +++ b/src/internal.c @@ -63,6 +63,8 @@ CYASSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #endif +static int BuildMessage(CYASSL* ssl, byte* output, int outSz, + const byte* input, int inSz, int type); #ifndef NO_CYASSL_CLIENT static int DoHelloVerifyRequest(CYASSL* ssl, const byte* input, word32*, @@ -2008,6 +2010,14 @@ void SSL_ResourceFree(CYASSL* ssl) /* Free any handshake resources no longer needed */ void FreeHandshakeResources(CYASSL* ssl) { + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { + CYASSL_MSG("Secure Renegottation needs to retain handshake resources"); + return; + } +#endif + /* input buffer */ if (ssl->buffers.inputBuffer.dynamicFlag) ShrinkInputBuffer(ssl, NO_FORCED_FREE); @@ -4351,6 +4361,10 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx, if (ret == 0 && ssl->options.side == CYASSL_CLIENT_END) ssl->options.serverState = SERVER_CERT_COMPLETE; + if (ssl->keys.encryptionOn) { + *inOutIdx += ssl->keys.padSz; + } + return ret; } @@ -4468,9 +4482,11 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx, if (*inOutIdx + size > totalSz) return INCOMPLETE_DATA; - ret = HashInput(ssl, input + *inOutIdx, size); - if (ret != 0) - return ret; + /* hello_request not hashed */ + if (type != hello_request) { + ret = HashInput(ssl, input + *inOutIdx, size); + if (ret != 0) return ret; + } #ifdef CYASSL_CALLBACKS /* add name later, add on record and handshake header part back on */ @@ -4558,6 +4574,9 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx, AddLateName("ServerHelloDone", &ssl->timeoutInfo); #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; + if (ssl->keys.encryptionOn) { + *inOutIdx += ssl->keys.padSz; + } break; case finished: @@ -6245,6 +6264,11 @@ int ProcessReply(CYASSL* ssl) } #endif + if (ssl->keys.encryptionOn && ssl->options.handShakeDone) { + ssl->buffers.inputBuffer.idx += ssl->keys.padSz; + ssl->curSize -= ssl->buffers.inputBuffer.idx; + } + if (ssl->curSize != 1) { CYASSL_MSG("Malicious or corrupted ChangeCipher msg"); return LENGTH_ERROR; @@ -6371,6 +6395,11 @@ int SendChangeCipher(CYASSL* ssl) } #endif + /* are we in scr */ + if (ssl->keys.encryptionOn && ssl->options.handShakeDone) { + sendSz += MAX_MSG_EXTRA; + } + /* check for avalaible size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -6383,6 +6412,17 @@ int SendChangeCipher(CYASSL* ssl) output[idx] = 1; /* turn it on */ + if (ssl->keys.encryptionOn && ssl->options.handShakeDone) { + byte input[ENUM_LEN]; + int inputSz = ENUM_LEN; + + input[0] = 1; /* turn it on */ + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + change_cipher_spec); + if (sendSz < 0) + return sendSz; + } + #ifdef CYASSL_DTLS if (ssl->options.dtls) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) @@ -8623,6 +8663,9 @@ static void PickHashSigAlgo(CYASSL* ssl, } #endif + if (ssl->keys.encryptionOn) + sendSz += MAX_MSG_EXTRA; + /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -8710,6 +8753,26 @@ static void PickHashSigAlgo(CYASSL* ssl, } #endif + if (ssl->keys.encryptionOn) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input,inputSz,handshake); + XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } + #ifdef CYASSL_DTLS if (ssl->options.dtls) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) @@ -8717,10 +8780,6 @@ static void PickHashSigAlgo(CYASSL* ssl, } #endif - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) - return ret; - ssl->options.clientState = CLIENT_HELLO_COMPLETE; #ifdef CYASSL_CALLBACKS @@ -8938,6 +8997,10 @@ static void PickHashSigAlgo(CYASSL* ssl, } #endif + if (ssl->keys.encryptionOn) { + *inOutIdx += ssl->keys.padSz; + } + return SetCipherSpecs(ssl); } @@ -9820,6 +9883,9 @@ static void PickHashSigAlgo(CYASSL* ssl, } #endif + if (ssl->keys.encryptionOn) + sendSz += MAX_MSG_EXTRA; + /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -9835,8 +9901,29 @@ static void PickHashSigAlgo(CYASSL* ssl, idx += 2; } XMEMCPY(output + idx, encSecret, encSz); - /* if add more to output, adjust idx - idx += encSz; */ + idx += encSz; + + if (ssl->keys.encryptionOn) { + byte* input; + int inputSz = idx-RECORD_HEADER_SZ; /* buildmsg adds rechdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake); + XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (sendSz < 0) + return sendSz; + } else { + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } + #ifdef CYASSL_DTLS if (ssl->options.dtls) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) @@ -9844,10 +9931,6 @@ static void PickHashSigAlgo(CYASSL* ssl, } #endif - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) - return ret; - #ifdef CYASSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); diff --git a/src/keys.c b/src/keys.c index 51a5f16d9..692f3404b 100644 --- a/src/keys.c +++ b/src/keys.c @@ -2282,14 +2282,24 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, /* Set encrypt/decrypt or both sides of key setup */ int SetKeysSide(CYASSL* ssl, enum encrypt_side side) { - int devId = NO_CAVIUM_DEVICE; + int devId = NO_CAVIUM_DEVICE, ret, copy = 0; Ciphers* encrypt = NULL; Ciphers* decrypt = NULL; + Keys* keys = &ssl->keys; + + (void)copy; #ifdef HAVE_CAVIUM devId = ssl->devId; #endif +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status) { + keys = &ssl->secure_renegotiation->tmp_keys; + copy = 1; + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + switch (side) { case ENCRYPT_SIDE_ONLY: encrypt = &ssl->encrypt; @@ -2308,8 +2318,50 @@ int SetKeysSide(CYASSL* ssl, enum encrypt_side side) return BAD_FUNC_ARG; } - return SetKeys(encrypt, decrypt, &ssl->keys, &ssl->specs, ssl->options.side, - ssl->heap, devId); + ret = SetKeys(encrypt, decrypt, keys, &ssl->specs, ssl->options.side, + ssl->heap, devId); + +#ifdef HAVE_SECURE_RENEGOTIATION + if (copy) { + int clientCopy = 0; + + if (ssl->options.side == CYASSL_CLIENT_END && encrypt) + clientCopy = 1; + else if (ssl->options.side == CYASSL_SERVER_END && decrypt) + clientCopy = 1; + + if (clientCopy) { + XMEMCPY(ssl->keys.client_write_MAC_secret, + keys->client_write_MAC_secret, MAX_DIGEST_SIZE); + XMEMCPY(ssl->keys.client_write_key, + keys->client_write_key, AES_256_KEY_SIZE); + XMEMCPY(ssl->keys.client_write_IV, + keys->client_write_IV, AES_IV_SIZE); + } else { + XMEMCPY(ssl->keys.server_write_MAC_secret, + keys->server_write_MAC_secret, MAX_DIGEST_SIZE); + XMEMCPY(ssl->keys.server_write_key, + keys->server_write_key, AES_256_KEY_SIZE); + XMEMCPY(ssl->keys.server_write_IV, + keys->server_write_IV, AES_IV_SIZE); + } + if (encrypt) { + ssl->keys.sequence_number = keys->sequence_number; + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + /* Initialize the AES-GCM/CCM explicit IV to a zero. */ + XMEMCPY(ssl->keys.aead_exp_IV, keys->aead_exp_IV, + AEAD_EXP_IV_SZ); + } + #endif + } + if (decrypt) + ssl->keys.peer_sequence_number = keys->peer_sequence_number; + ssl->secure_renegotiation->cache_status++; + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + + return ret; } @@ -2317,29 +2369,38 @@ int SetKeysSide(CYASSL* ssl, enum encrypt_side side) int StoreKeys(CYASSL* ssl, const byte* keyData) { int sz, i = 0; + Keys* keys = &ssl->keys; + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status == + SCR_CACHE_NEEDED) { + keys = &ssl->secure_renegotiation->tmp_keys; + ssl->secure_renegotiation->cache_status++; + } +#endif /* HAVE_SECURE_RENEGOTIATION */ if (ssl->specs.cipher_type != aead) { sz = ssl->specs.hash_size; - XMEMCPY(ssl->keys.client_write_MAC_secret,&keyData[i], sz); + XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); i += sz; - XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz); + XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); i += sz; } sz = ssl->specs.key_size; - XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz); + XMEMCPY(keys->client_write_key, &keyData[i], sz); i += sz; - XMEMCPY(ssl->keys.server_write_key, &keyData[i], sz); + XMEMCPY(keys->server_write_key, &keyData[i], sz); i += sz; sz = ssl->specs.iv_size; - XMEMCPY(ssl->keys.client_write_IV, &keyData[i], sz); + XMEMCPY(keys->client_write_IV, &keyData[i], sz); i += sz; - XMEMCPY(ssl->keys.server_write_IV, &keyData[i], sz); + XMEMCPY(keys->server_write_IV, &keyData[i], sz); #ifdef HAVE_AEAD if (ssl->specs.cipher_type == aead) { /* Initialize the AES-GCM/CCM explicit IV to a zero. */ - XMEMSET(ssl->keys.aead_exp_IV, 0, AEAD_EXP_IV_SZ); + XMEMSET(keys->aead_exp_IV, 0, AEAD_EXP_IV_SZ); } #endif diff --git a/src/ssl.c b/src/ssl.c index 82af92958..0f5357fb9 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -717,6 +717,7 @@ int CyaSSL_CTX_UseSupportedCurve(CYASSL_CTX* ctx, word16 name) /* Secure Renegotiation */ #ifdef HAVE_SECURE_RENEGOTIATION +/* user is forcing ability to use secure renegotiation, we discourage it */ int CyaSSL_UseSecureRenegotiation(CYASSL* ssl) { int ret = BAD_FUNC_ARG; @@ -734,9 +735,70 @@ int CyaSSL_UseSecureRenegotiation(CYASSL* ssl) return ret; } + +/* do a secure renegotiation handshake, use forced, we discourage */ +int CyaSSL_Rehandshake(CYASSL* ssl) +{ + int ret; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->secure_renegotiation == NULL) { + CYASSL_MSG("Secure Renegotiation not forced on by user"); + return SECURE_RENEGOTIATION_E; + } + + if (ssl->secure_renegotiation->enabled == 0) { + CYASSL_MSG("Secure Renegotiation not enabled at extension level"); + return SECURE_RENEGOTIATION_E; + } + + if (ssl->options.handShakeState != HANDSHAKE_DONE) { + CYASSL_MSG("Can't renegotiate until previous handshake complete"); + return SECURE_RENEGOTIATION_E; + } + + /* reset handshake states */ + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN; + ssl->options.handShakeState = NULL_STATE; + ssl->options.processReply = 0; /* TODO, move states in internal.h */ + + ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; + +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + InitMd5(&ssl->hashMd5); +#endif +#ifndef NO_SHA + ret = InitSha(&ssl->hashSha); + if (ret !=0) + return ret; +#endif +#endif /* NO_OLD_TLS */ +#ifndef NO_SHA256 + ret = InitSha256(&ssl->hashSha256); + if (ret !=0) + return ret; +#endif +#ifdef CYASSL_SHA384 + ret = InitSha384(&ssl->hashSha384); + if (ret !=0) + return ret; #endif + ret = CyaSSL_negotiate(ssl); + return ret; +} + +#endif /* HAVE_SECURE_RENEGOTIATION */ + + #ifndef CYASSL_LEANPSK + int CyaSSL_send(CYASSL* ssl, const void* data, int sz, int flags) { int ret;