From d168d60adef039256d86cc4e7fc627ecd6343a23 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 2 Oct 2018 15:38:45 -0700 Subject: [PATCH] Server Side Secure Renegotiation 1. Add enables to the example server for turning on secure renegotiation. 2. Add encryption assists to the handhshake message handler functions. 3. Add a hello request message function. Includes handshake timing pre/postambles. --- examples/server/server.c | 58 +++++- src/internal.c | 383 +++++++++++++++++++++++++++++------- src/ssl.c | 6 + src/tls.c | 41 ++-- wolfcrypt/src/logging.c | 2 + wolfssl/internal.h | 7 +- wolfssl/wolfcrypt/logging.h | 4 +- 7 files changed, 410 insertions(+), 91 deletions(-) diff --git a/examples/server/server.c b/examples/server/server.c index 85248e86b..47a4af5a3 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -613,6 +613,10 @@ static void Usage(void) printf("%s", msg[++msgId]); /* -N */ printf("%s", msg[++msgId]); /* -S */ printf("%s", msg[++msgId]); /* -w */ +#ifdef HAVE_SECURE_RENEGOTIATION + printf("-M Allow Secure Renegotiation\n"); + printf("-m Force Server Initiated Secure Renegotiation\n"); +#endif /* HAVE_SECURE_RENEGOTIATION */ #ifdef HAVE_OCSP printf("%s", msg[++msgId]); /* -o */ printf("%s", msg[++msgId]); /* -O */ @@ -780,6 +784,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_EARLY_DATA int earlyData = 0; #endif +#ifdef HAVE_SECURE_RENEGOTIATION + int scr = 0; + int forceScr = 0; +#endif /* HAVE_SECURE_RENEGOTIATION */ #ifdef WOLFSSL_SEND_HRR_COOKIE int hrrCookie = 0; #endif @@ -851,10 +859,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_VXWORKS useAnyAddr = 1; #else - /* Not Used: h, m, z, F, M, T, V, W, X */ - while ((ch = mygetopt(argc, argv, "?:" - "abc:defgijk:l:nop:q:rstuv:wxy" - "A:B:C:D:E:GH:IJKL:NO:PQR:S:TUVYZ:" + /* Not Used: h, z, F, T, V, W, X */ + while ((ch = mygetopt(argc, argv, "?" + "abc:defgijk:l:mnop:q:rstuv:wxy" + "A:B:C:D:E:GH:IJKL:MNO:PQR:S:TUVYZ:" "01:23:")) != -1) { switch (ch) { case '?' : @@ -1161,6 +1169,19 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif break; + case 'M' : + #ifdef HAVE_SECURE_RENEGOTIATION + scr = 1; + #endif /* HAVE_SECURE_RENEGOTIATION */ + break; + + case 'm' : + #ifdef HAVE_SECURE_RENEGOTIATION + scr = 1; + forceScr = 1; + #endif /* HAVE_SECURE_RENEGOTIATION */ + break; + case '0' : #ifdef WOLFSSL_EARLY_DATA earlyData = 1; @@ -1639,7 +1660,15 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) err_sys("unable to set mcast secret"); #endif } - +#if 0 +#ifdef HAVE_SECURE_RENEGOTIATION + if (scr) { + if (wolfSSL_UseSecureRenegotiation(ssl) != WOLFSSL_SUCCESS) { + err_sys_ex(runWithErrors, "can't enable secure renegotiation"); + } + } +#endif /* HAVE_SECURE_RENEGOTIATION */ +#endif #ifndef NO_HANDSHAKE_DONE_CB wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL); #endif @@ -1957,6 +1986,25 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) err = SSL_get_error(ssl, 0); } +#if defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) + if (scr && forceScr) { + if (nonBlocking) { + printf("not doing secure renegotiation on example with" + " nonblocking yet"); + } else { + if (wolfSSL_Rehandshake(ssl) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + printf("err = %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("wolfSSL_Rehandshake failed"); + } + } + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + if (err != WOLFSSL_ERROR_ZERO_RETURN && echoData == 0 && throughput == 0) { const char* write_msg; diff --git a/src/internal.c b/src/internal.c index 9973dabfb..41f1fe0b9 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4900,12 +4900,14 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #endif #ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->options.side == WOLFSSL_CLIENT_END) { /* use secure renegotiation by default (not recommend) */ #ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT ret = wolfSSL_UseSecureRenegotiation(ssl); if (ret != WOLFSSL_SUCCESS) return ret; #endif + } #endif return 0; @@ -10250,6 +10252,9 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ret != 0) SendAlert(ssl, alert_fatal, bad_certificate_status_response); + if (IsEncryptionOn(ssl, 0)) + *inOutIdx += ssl->keys.padSz; + WOLFSSL_LEAVE("DoCertificateStatus", ret); WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_DO); @@ -10267,6 +10272,9 @@ static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { (void)input; + WOLFSSL_START(WC_FUNC_HELLO_REQUEST_DO); + WOLFSSL_ENTER("DoFinished"); + if (size) /* must be 0 */ return BUFFER_ERROR; @@ -10285,6 +10293,8 @@ static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_SECURE_RENEGOTIATION else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { ssl->secure_renegotiation->startScr = 1; + WOLFSSL_LEAVE("DoHelloRequest", 0); + WOLFSSL_END(WC_FUNC_HELLO_REQUEST_DO); return 0; } #endif @@ -10330,6 +10340,7 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, else XMEMCPY(ssl->secure_renegotiation->client_verify_data, input + *inOutIdx, TLS_FINISHED_SZ); + ssl->secure_renegotiation->verifySet = 1; } #endif @@ -10699,6 +10710,28 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, expectedIdx = *inOutIdx + size + (ssl->keys.encryptionOn ? ssl->keys.padSz : 0); +#if !defined(WOLFSSL_NO_SERVER) && \ + defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) + if (ssl->options.handShakeDone && type == client_hello && + ssl->secure_renegotiation && + ssl->secure_renegotiation->enabled) + { + WOLFSSL_MSG("Reset handshake state"); + XMEMSET(&ssl->msgsReceived, 0, sizeof(MsgsReceived)); + 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->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; + + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + } +#endif + /* sanity check msg received */ if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) { WOLFSSL_MSG("Sanity Check on handshake message type received failed"); @@ -10881,6 +10914,13 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, } } #endif + if (IsEncryptionOn(ssl, 0)) { + /* access beyond input + size should be checked against totalSz */ + if (*inOutIdx + ssl->keys.padSz > totalSz) + return BUFFER_E; + + *inOutIdx += ssl->keys.padSz; + } break; case client_key_exchange: @@ -14617,12 +14657,16 @@ int SendCertificateRequest(WOLFSSL* ssl) sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz; + if (!ssl->options.dtls) { + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + } + else { #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; #endif + } /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -14675,18 +14719,34 @@ int SendCertificateRequest(WOLFSSL* ssl) #endif (void)i; - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) return ret; } - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) - return ret; #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) @@ -15197,10 +15257,10 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) startScr: if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) { int err; - ssl->secure_renegotiation->startScr = 0; /* only start once */ WOLFSSL_MSG("Need to start scr, server requested"); if ( (err = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) return err; + ssl->secure_renegotiation->startScr = 0; /* only start once */ } #endif @@ -17162,6 +17222,10 @@ exit_dpk: return sendSz; } else { #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } if (ssl->options.dtls) DtlsSEQIncrement(ssl, CUR_ORDER); #endif @@ -17170,13 +17234,6 @@ exit_dpk: return ret; } - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif - ssl->options.clientState = CLIENT_HELLO_COMPLETE; #ifdef OPENSSL_EXTRA ssl->cbmode = SSL_CB_MODE_WRITE; @@ -21059,7 +21116,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* WOLFSSL_DTLS */ - /* check for available size */ + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + /* check for avalaible size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -21138,9 +21198,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* last, extensions */ #ifdef HAVE_TLS_EXTENSIONS - ret = TLSX_WriteResponse(ssl, output + idx, server_hello, NULL); - if (ret != 0) - return ret; + { + word16 offset = 0; + ret = TLSX_WriteResponse(ssl, output + idx, server_hello, &offset); + if (ret != 0) + return ret; + idx += offset; + } #else #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) { @@ -21157,21 +21221,30 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif #endif - ssl->buffers.outputBuffer.length += sendSz; - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return ret; - } + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ - if (ssl->options.dtls) { - DtlsSEQIncrement(ssl, CUR_ORDER); - } - #endif + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) - return ret; + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) @@ -21182,6 +21255,18 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif ssl->options.serverState = SERVER_HELLO_COMPLETE; + ssl->buffers.outputBuffer.length += sendSz; + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + + if (ssl->options.dtls) { + DtlsSEQIncrement(ssl, CUR_ORDER); + } + #endif if (ssl->options.groupMessages) ret = 0; @@ -21294,6 +21379,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA byte* verifySig; #endif + byte* input; word32 idx; word32 tmpSigSz; word32 length; @@ -21309,6 +21395,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 qshSz; #endif int sendSz; + int inputSz; } SskeArgs; static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs) @@ -21606,6 +21693,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + /* check for available size */ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; @@ -21665,6 +21757,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + /* check for available size */ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; @@ -21767,6 +21863,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + /* check for available size */ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; @@ -21983,6 +22084,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, preSigIdx = args->idx; } #endif + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + /* check for available size */ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; @@ -22219,6 +22324,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + /* check for available size */ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; @@ -22697,20 +22806,45 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* HAVE_ECC || HAVE_CURVE25519 */ - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { - goto exit_sske; + if (IsEncryptionOn(ssl, 1)) { + args->inputSz = args->length + HANDSHAKE_HEADER_SZ; + /* buildmsg adds rechdr */ + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + ret = BuildMessage(ssl, args->output, args->sendSz, + args->input, args->inputSz, handshake, 1, 0, 0); + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; + /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; } } + else { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, + args->output, args->sendSz)) != 0) { + goto exit_sske; + } + } - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif - ret = HashOutput(ssl, args->output, args->sendSz, 0); - if (ret != 0) { - goto exit_sske; + ret = HashOutput(ssl, args->output, args->sendSz, 0); + if (ret != 0) { + goto exit_sske; + } } #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) @@ -23745,6 +23879,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } ret = MatchSuite(ssl, &clSuites); +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled && + IsEncryptionOn(ssl, 0)) { + ssl->secure_renegotiation->startScr = 1; + } +#endif WOLFSSL_LEAVE("DoClientHello", ret); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); @@ -24053,6 +24193,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case TLS_ASYNC_FINALIZE: { + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + } + ssl->options.havePeerVerify = 1; /* Set final index */ @@ -24118,6 +24262,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; #endif + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -24128,19 +24275,34 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, AddHeaders(output, 0, server_hello_done, ssl); - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return 0; - } + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */ - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; - ret = HashOutput(ssl, output, sendSz, 0); + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, output, sendSz, 0); if (ret != 0) return ret; + } #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) @@ -24409,12 +24571,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, length += ssl->session.ticketLen; sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + if (!ssl->options.dtls) { + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) + sendSz += MAX_MSG_EXTRA; + } + else { #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - } #endif + } /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -24435,19 +24601,38 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* ticket */ XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); - /* idx += ssl->session.ticketLen; */ + idx += ssl->session.ticketLen; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return ret; + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ - DtlsSEQIncrement(ssl, CUR_ORDER); + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } + else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + + DtlsSEQIncrement(ssl, CUR_ORDER); + } + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; } - #endif - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) return ret; ssl->buffers.outputBuffer.length += sendSz; ret = SendBuffered(ssl); @@ -24462,6 +24647,62 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef WOLFSSL_NO_TLS12 +#if defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) && \ + !defined(WOLFSSL_NO_SERVER) + + /* handle generation of server's hello_request (0) */ + int SendHelloRequest(WOLFSSL* ssl) + { + byte* output; + int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int ret; + + WOLFSSL_START(WC_FUNC_HELLO_REQUEST_SEND); + WOLFSSL_ENTER("SendHelloRequest"); + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, 0, hello_request, ssl); + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 0, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendHelloRequest", ret); + WOLFSSL_END(WC_FUNC_HELLO_REQUEST_SEND); + + return ret; + } + +#endif /* HAVE_SECURE_RENEGOTIATION && HAVE_SERVER_RENEGOTIATION_INFO */ + #ifdef WOLFSSL_DTLS /* handle generation of DTLS hello_verify_request (3) */ static int SendHelloVerifyRequest(WOLFSSL* ssl, @@ -25547,6 +25788,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case TLS_ASYNC_FINALIZE: { + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + } + #ifdef HAVE_QSH word16 name; diff --git a/src/ssl.c b/src/ssl.c index 6ebc05724..b7b6ce808 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2390,6 +2390,12 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl) ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; + if (ssl->options.side == WOLFSSL_SERVER_END) { + ret = SendHelloRequest(ssl); + if (ret != 0) + return ret; + } + ret = InitHandshakeHashes(ssl); if (ret !=0) return ret; diff --git a/src/tls.c b/src/tls.c index a916eae4d..cbcb15d28 100644 --- a/src/tls.c +++ b/src/tls.c @@ -34,7 +34,7 @@ #include #include #ifdef NO_INLINE - #include + #else #define WOLFSSL_MISC_INCLUDED #include @@ -4307,7 +4307,7 @@ static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data, byte length = OPAQUE8_LEN; /* empty info length */ /* data will be NULL for HAVE_SERVER_RENEGOTIATION_INFO only */ - if (data && data->enabled) { + if (data && data->enabled && data->verifySet) { /* client sends client_verify_data only */ length += TLS_FINISHED_SZ; @@ -4323,8 +4323,7 @@ static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data, byte* output, int isRequest) { word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */ - - if (data && data->enabled) { + if (data && data->enabled && data->verifySet) { /* client sends client_verify_data only */ XMEMCPY(output + offset, data->client_verify_data, TLS_FINISHED_SZ); offset += TLS_FINISHED_SZ; @@ -4352,15 +4351,16 @@ static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input, if (isRequest && *input == 0) { #ifdef HAVE_SERVER_RENEGOTIATION_INFO if (length == OPAQUE8_LEN) { - if (TLSX_Find(ssl->extensions, - TLSX_RENEGOTIATION_INFO) == NULL) { - ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = 0; - - } else { - ret = 0; + ret = TLSX_UseSecureRenegotiation(&ssl->extensions, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + ret = 0; + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); + if (extension) { + ssl->secure_renegotiation = (SecureRenegotiation*)extension->data; + extension->resp = 1; + ssl->secure_renegotiation->enabled = 1; } } #else @@ -4378,8 +4378,19 @@ static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input, else if (isRequest) { #ifndef NO_WOLFSSL_SERVER if (*input == TLS_FINISHED_SZ) { - /* TODO compare client_verify_data */ - ret = 0; + input++; /* get past size */ + + /* validate client verify data */ + if (XMEMCMP(input, + ssl->secure_renegotiation->client_verify_data, + TLS_FINISHED_SZ) == 0) { + WOLFSSL_MSG("SCR client verify data match"); + ret = 0; /* verified */ + TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO); + } else { + /* already in error state */ + WOLFSSL_MSG("SCR client verify data Failure"); + } } #endif } diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index f091d9f01..063d8ffaf 100644 --- a/wolfcrypt/src/logging.c +++ b/wolfcrypt/src/logging.c @@ -64,6 +64,8 @@ static struct wc_error_queue* wc_last_node; static double wc_func_start[WC_FUNC_COUNT]; static double wc_func_time[WC_FUNC_COUNT] = { 0, }; static const char* wc_func_name[WC_FUNC_COUNT] = { + "SendHelloRequest", + "DoHelloRequest", "SendClientHello", "DoClientHello", "SendServerHello", diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 2cb9cce87..e6db2484b 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2272,6 +2272,7 @@ enum key_cache_state { /* Additional Connection State according to rfc5746 section 3.1 */ typedef struct SecureRenegotiation { byte enabled; /* secure_renegotiation flag in rfc */ + byte verifySet; byte startScr; /* server requested client to start scr */ enum key_cache_state cache_status; /* track key cache state */ byte client_verify_data[TLS_FINISHED_SZ]; /* cached */ @@ -2511,7 +2512,7 @@ struct WOLFSSL_CTX { #ifdef HAVE_EXT_CACHE byte internalCacheOff:1; #endif - byte sendVerify; /* for client side (can not be single bit) */ + byte sendVerify:2; /* for client side (can not be single bit) */ byte haveRSA:1; /* RSA available */ byte haveECC:1; /* ECC available */ byte haveDH:1; /* server DH parms set by user */ @@ -4032,6 +4033,10 @@ WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*); || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) WOLFSSL_LOCAL int CreateOcspResponse(WOLFSSL*, OcspRequest**, buffer*); #endif +#if defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) +WOLFSSL_LOCAL int SendHelloRequest(WOLFSSL*); +#endif WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*); WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL*); WOLFSSL_LOCAL int SendBuffered(WOLFSSL*); diff --git a/wolfssl/wolfcrypt/logging.h b/wolfssl/wolfcrypt/logging.h index 19ea0e5cd..ddb888b29 100644 --- a/wolfssl/wolfcrypt/logging.h +++ b/wolfssl/wolfcrypt/logging.h @@ -51,7 +51,9 @@ enum wc_LogLevels { * Do not use WOLFSSL_FUNC_TIME in production code. */ enum wc_FuncNum { - WC_FUNC_CLIENT_HELLO_SEND = 0, + WC_FUNC_HELLO_REQUEST_SEND = 0, + WC_FUNC_HELLO_REQUEST_DO, + WC_FUNC_CLIENT_HELLO_SEND, WC_FUNC_CLIENT_HELLO_DO, WC_FUNC_SERVER_HELLO_SEND, WC_FUNC_SERVER_HELLO_DO,