From b7caab938efe4566c2f3df44f74c6c37212353e3 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 8 Jun 2018 17:34:03 +1000 Subject: [PATCH] Fix post authentication for TLS 1.3 --- examples/client/client.c | 12 ++-- examples/server/server.c | 55 ++------------- src/tls.c | 22 +++--- src/tls13.c | 147 ++++++++++++++++++++++----------------- 4 files changed, 105 insertions(+), 131 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index b7f2a37c3..f90356c83 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -660,7 +660,11 @@ static void ClientWrite(WOLFSSL* ssl, char* msg, int msgSz) } #endif } - } while (err == WC_PENDING_E); + } while (err == WOLFSSL_ERROR_WANT_WRITE + #ifdef WOLFSSL_ASYNC_CRYPT + || err == WC_PENDING_E + #endif + ); if (ret != msgSz) { printf("SSL_write msg error %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); @@ -925,9 +929,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int onlyKeyShare = 0; #ifdef WOLFSSL_TLS13 int noPskDheKe = 0; -#ifdef WOLFSSL_POST_HANDSHAKE_AUTH int postHandAuth = 0; -#endif #endif int updateKeysIVs = 0; #ifdef WOLFSSL_EARLY_DATA @@ -2253,8 +2255,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) ClientRead(ssl, reply, sizeof(reply)-1, 1); -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) - if (postHandAuth) +#if defined(WOLFSSL_TLS13) + if (updateKeysIVs || postHandAuth) ClientWrite(ssl, msg, msgSz); #endif if (sendGET) { /* get html */ diff --git a/examples/server/server.c b/examples/server/server.c index b2fa31ad2..f744a96c6 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -281,46 +281,6 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, return EXIT_SUCCESS; } -#ifdef WOLFSSL_TLS13 -static void NonBlockingServerRead(WOLFSSL* ssl, char* input, int inputLen) -{ - int ret, err; - char buffer[CYASSL_MAX_ERROR_SZ]; - - /* Read data */ - do { - err = 0; /* reset error */ - ret = SSL_read(ssl, input, inputLen); - if (ret < 0) { - err = SSL_get_error(ssl, 0); - - #ifdef WOLFSSL_ASYNC_CRYPT - if (err == WC_PENDING_E) { - ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); - if (ret < 0) break; - } - else - #endif - #ifdef CYASSL_DTLS - if (wolfSSL_dtls(ssl) && err == DECRYPT_ERROR) { - printf("Dropped client's message due to a bad MAC\n"); - } - else - #endif - if (err != WOLFSSL_ERROR_WANT_READ) { - printf("SSL_read input error %d, %s\n", err, - ERR_error_string(err, buffer)); - err_sys_ex(runWithErrors, "SSL_read failed"); - } - } - } while (err == WC_PENDING_E || err == WOLFSSL_ERROR_WANT_READ); - if (ret > 0) { - input[ret] = 0; /* null terminate message */ - printf("Client message: %s\n", input); - } -} -#endif - static void ServerRead(WOLFSSL* ssl, char* input, int inputLen) { int ret, err; @@ -352,7 +312,7 @@ static void ServerRead(WOLFSSL* ssl, char* input, int inputLen) err_sys_ex(runWithErrors, "SSL_read failed"); } } - } while (err == WC_PENDING_E); + } while (err == WC_PENDING_E || err == WOLFSSL_ERROR_WANT_READ); if (ret > 0) { input[ret] = 0; /* null terminate message */ printf("Client message: %s\n", input); @@ -1627,7 +1587,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) if (postHandAuth) { - SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | + SSL_set_verify(ssl, WOLFSSL_VERIFY_PEER | ((usePskPlus) ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK : WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0); if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) @@ -1637,7 +1597,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } #ifdef WOLFSSL_TRUST_PEER_CERT if (trustCert) { - if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, + if ((ret = wolfSSL_trust_peer_cert(ssl, trustCert, WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { err_sys_ex(runWithErrors, "can't load trusted peer cert " "file"); @@ -1679,13 +1639,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) ServerWrite(ssl, write_msg, write_msg_sz); #ifdef WOLFSSL_TLS13 - if (updateKeysIVs || postHandAuth) { - ServerWrite(ssl, write_msg, write_msg_sz); - if (nonBlocking) - NonBlockingServerRead(ssl, input, sizeof(input)-1); - else - ServerRead(ssl, input, sizeof(input)-1); - } + if (updateKeysIVs || postHandAuth) + ServerRead(ssl, input, sizeof(input)-1); #endif } else { diff --git a/src/tls.c b/src/tls.c index df8ac64f5..0920bc081 100644 --- a/src/tls.c +++ b/src/tls.c @@ -7328,7 +7328,7 @@ int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes) static word16 TLSX_PostHandAuth_GetSize(byte msgType) { if (msgType == client_hello) - return OPAQUE8_LEN; + return 0; return SANITY_MSG_E; } @@ -7343,10 +7343,10 @@ static word16 TLSX_PostHandAuth_GetSize(byte msgType) */ static word16 TLSX_PostHandAuth_Write(byte* output, byte msgType) { - if (msgType == client_hello) { - *output = 0; - return OPAQUE8_LEN; - } + (void)output; + + if (msgType == client_hello) + return 0; return SANITY_MSG_E; } @@ -7363,15 +7363,11 @@ static word16 TLSX_PostHandAuth_Write(byte* output, byte msgType) static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType) { - byte len; + (void)input; if (msgType == client_hello) { - /* Ensure length byte exists. */ - if (length < OPAQUE8_LEN) - return BUFFER_E; - - len = input[0]; - if (length - OPAQUE8_LEN != len || len != 0) + /* Ensure extension is empty. */ + if (length != 0) return BUFFER_E; ssl->options.postHandshakeAuth = 1; @@ -9347,7 +9343,7 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, #ifdef WOLFSSL_POST_HANDSHAKE_AUTH case TLSX_POST_HANDSHAKE_AUTH: - WOLFSSL_MSG("PSK Key Exchange Modes extension received"); + WOLFSSL_MSG("Post Handshake Authentication extension received"); if (!IsAtLeastTLSv1_3(ssl->version)) break; diff --git a/src/tls13.c b/src/tls13.c index 75bc5ddc1..545dfcfd0 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3202,16 +3202,6 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, /* This message is always encrypted so add encryption padding. */ *inOutIdx += ssl->keys.padSz; -#if !defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) - if (ssl->options.side == WOLFSSL_CLIENT_END && - ssl->options.handShakeState == HANDSHAKE_DONE) { - /* reset handshake states */ - ssl->options.clientState = CLIENT_HELLO_COMPLETE; - ssl->options.connectState = FIRST_REPLY_DONE; - ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; - } -#endif - WOLFSSL_LEAVE("DoTls13CertificateRequest", ret); WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO); @@ -5855,7 +5845,15 @@ static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (*inOutIdx + size + ssl->keys.padSz > totalSz) return BUFFER_E; - if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.handShakeDone) { + ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.client_write_MAC_secret; + } + else if (ssl->options.side == WOLFSSL_CLIENT_END) { /* All the handshake messages have been received to calculate * client and server finished keys. */ @@ -5961,7 +5959,15 @@ static int SendTls13Finished(WOLFSSL* ssl) AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); /* make finished hashes */ - if (ssl->options.side == WOLFSSL_CLIENT_END) + if (ssl->options.handShakeDone) { + ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.client_write_MAC_secret; + } + else if (ssl->options.side == WOLFSSL_CLIENT_END) secret = ssl->keys.client_write_MAC_secret; else { /* All the handshake messages have been done to calculate client and @@ -6864,13 +6870,14 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) ssl->arrays->psk_keySz != 0) { WOLFSSL_MSG("CertificateRequset received while using PSK"); return SANITY_MSG_E; - return SANITY_MSG_E; } #endif + #ifndef WOLFSSL_POST_HANDSHAKE_AUTH if (ssl->msgsReceived.got_certificate_request) { WOLFSSL_MSG("Duplicate CertificateRequest received"); return DUPLICATE_MSG_E; } + #endif ssl->msgsReceived.got_certificate_request = 1; break; @@ -6878,20 +6885,20 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) case certificate_verify: #ifndef NO_WOLFSSL_CLIENT - if (ssl->options.side == WOLFSSL_CLIENT_END && - ssl->options.serverState != SERVER_CERT_COMPLETE) { - WOLFSSL_MSG("No Cert before CertVerify"); - return OUT_OF_ORDER_E; + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.serverState != SERVER_CERT_COMPLETE) { + WOLFSSL_MSG("No Cert before CertVerify"); + return OUT_OF_ORDER_E; + } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.serverState == SERVER_CERT_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("CertificateVerify received while using PSK"); + return SANITY_MSG_E; + } + #endif } - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - /* Server's authenticating with PSK must not send this. */ - if (ssl->options.side == WOLFSSL_CLIENT_END && - ssl->options.serverState == SERVER_CERT_COMPLETE && - ssl->arrays->psk_keySz != 0) { - WOLFSSL_MSG("CertificateVerify received while using PSK"); - return SANITY_MSG_E; - } - #endif #endif #ifndef NO_WOLFSSL_SERVER if (ssl->options.side == WOLFSSL_SERVER_END) { @@ -7134,47 +7141,61 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ssl->options.tls1_3) { /* Need to hash input message before deriving secrets. */ -#ifndef NO_WOLFSSL_CLIENT - if (type == server_hello && ssl->options.side == WOLFSSL_CLIENT_END) { - if ((ret = DeriveEarlySecret(ssl)) != 0) - return ret; - if ((ret = DeriveHandshakeSecret(ssl)) != 0) - return ret; + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (type == server_hello) { + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + if ((ret = DeriveHandshakeSecret(ssl)) != 0) + return ret; - if ((ret = DeriveTls13Keys(ssl, handshake_key, + if ((ret = DeriveTls13Keys(ssl, handshake_key, ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { - return ret; + return ret; + } + #ifdef WOLFSSL_EARLY_DATA + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + #else + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + #endif } - #ifdef WOLFSSL_EARLY_DATA - if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) - return ret; - #else - if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) - return ret; - #endif - } - if (type == finished && ssl->options.side == WOLFSSL_CLIENT_END) { - if ((ret = DeriveMasterSecret(ssl)) != 0) - return ret; - #ifdef WOLFSSL_EARLY_DATA - if ((ret = DeriveTls13Keys(ssl, traffic_key, + if (type == finished) { + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; + #ifdef WOLFSSL_EARLY_DATA + if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data)) != 0) { - return ret; - } - #else - if ((ret = DeriveTls13Keys(ssl, traffic_key, + return ret; + } + #else + if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { - return ret; + return ret; + } + #endif } - #endif + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + if (type == certificate_request && + ssl->options.handShakeState == HANDSHAKE_DONE) { + /* reset handshake states */ + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + ssl->options.connectState = FIRST_REPLY_DONE; + ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; + + if (wolfSSL_connect_TLSv13(ssl) != SSL_SUCCESS) + ret = POST_HAND_AUTH_ERROR; + } + #endif } -#endif /* NO_WOLFSSL_CLIENT */ + #endif /* NO_WOLFSSL_CLIENT */ #ifndef NO_WOLFSSL_SERVER #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (type == finished && ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.side == WOLFSSL_SERVER_END && type == finished) { ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); if (ret != 0) return ret; @@ -7497,14 +7518,9 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) FALL_THROUGH; case FIRST_REPLY_THIRD: - #if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) - if (!ssl->options.sendVerify || !ssl->options.postHandshakeAuth) - #endif - { - if ((ssl->error = SendTls13Finished(ssl)) != 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; } WOLFSSL_MSG("sent: finished"); @@ -7805,11 +7821,16 @@ int wolfSSL_request_certificate(WOLFSSL* ssl) certReqCtx->ctx = certReqCtx->next->ctx + 1; ssl->certReqCtx = certReqCtx; + ssl->msgsReceived.got_certificate = 0; + ssl->msgsReceived.got_certificate_verify = 0; + ssl->msgsReceived.got_finished = 0; + ret = SendTls13CertificateRequest(ssl, &certReqCtx->ctx, certReqCtx->len); if (ret == WANT_WRITE) ret = WOLFSSL_ERROR_WANT_WRITE; else if (ret == 0) ret = WOLFSSL_SUCCESS; + return ret; } #endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */