Merge pull request #1613 from SparkiDev/tls13_post_auth

Fix post authentication for TLS 1.3
This commit is contained in:
toddouska
2018-06-12 08:29:38 -07:00
committed by GitHub
4 changed files with 105 additions and 131 deletions

View File

@ -660,7 +660,11 @@ static void ClientWrite(WOLFSSL* ssl, char* msg, int msgSz)
} }
#endif #endif
} }
} while (err == WC_PENDING_E); } while (err == WOLFSSL_ERROR_WANT_WRITE
#ifdef WOLFSSL_ASYNC_CRYPT
|| err == WC_PENDING_E
#endif
);
if (ret != msgSz) { if (ret != msgSz) {
printf("SSL_write msg error %d, %s\n", err, printf("SSL_write msg error %d, %s\n", err,
wolfSSL_ERR_error_string(err, buffer)); wolfSSL_ERR_error_string(err, buffer));
@ -925,9 +929,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int onlyKeyShare = 0; int onlyKeyShare = 0;
#ifdef WOLFSSL_TLS13 #ifdef WOLFSSL_TLS13
int noPskDheKe = 0; int noPskDheKe = 0;
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
int postHandAuth = 0; int postHandAuth = 0;
#endif
#endif #endif
int updateKeysIVs = 0; int updateKeysIVs = 0;
#ifdef WOLFSSL_EARLY_DATA #ifdef WOLFSSL_EARLY_DATA
@ -2253,8 +2255,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
ClientRead(ssl, reply, sizeof(reply)-1, 1); ClientRead(ssl, reply, sizeof(reply)-1, 1);
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) #if defined(WOLFSSL_TLS13)
if (postHandAuth) if (updateKeysIVs || postHandAuth)
ClientWrite(ssl, msg, msgSz); ClientWrite(ssl, msg, msgSz);
#endif #endif
if (sendGET) { /* get html */ if (sendGET) { /* get html */

View File

@ -281,46 +281,6 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block,
return EXIT_SUCCESS; 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) static void ServerRead(WOLFSSL* ssl, char* input, int inputLen)
{ {
int ret, err; int ret, err;
@ -352,7 +312,7 @@ static void ServerRead(WOLFSSL* ssl, char* input, int inputLen)
err_sys_ex(runWithErrors, "SSL_read failed"); 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) { if (ret > 0) {
input[ret] = 0; /* null terminate message */ input[ret] = 0; /* null terminate message */
printf("Client message: %s\n", input); 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(NO_FILESYSTEM) && !defined(NO_CERTS)
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (postHandAuth) { if (postHandAuth) {
SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | SSL_set_verify(ssl, WOLFSSL_VERIFY_PEER |
((usePskPlus) ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK : ((usePskPlus) ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK :
WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0); WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0);
if (SSL_CTX_load_verify_locations(ctx, verifyCert, 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 #ifdef WOLFSSL_TRUST_PEER_CERT
if (trustCert) { if (trustCert) {
if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, if ((ret = wolfSSL_trust_peer_cert(ssl, trustCert,
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
err_sys_ex(runWithErrors, "can't load trusted peer cert " err_sys_ex(runWithErrors, "can't load trusted peer cert "
"file"); "file");
@ -1679,13 +1639,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
ServerWrite(ssl, write_msg, write_msg_sz); ServerWrite(ssl, write_msg, write_msg_sz);
#ifdef WOLFSSL_TLS13 #ifdef WOLFSSL_TLS13
if (updateKeysIVs || postHandAuth) { if (updateKeysIVs || postHandAuth)
ServerWrite(ssl, write_msg, write_msg_sz); ServerRead(ssl, input, sizeof(input)-1);
if (nonBlocking)
NonBlockingServerRead(ssl, input, sizeof(input)-1);
else
ServerRead(ssl, input, sizeof(input)-1);
}
#endif #endif
} }
else { else {

View File

@ -7792,7 +7792,7 @@ int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes)
static word16 TLSX_PostHandAuth_GetSize(byte msgType) static word16 TLSX_PostHandAuth_GetSize(byte msgType)
{ {
if (msgType == client_hello) if (msgType == client_hello)
return OPAQUE8_LEN; return 0;
return SANITY_MSG_E; return SANITY_MSG_E;
} }
@ -7807,10 +7807,10 @@ static word16 TLSX_PostHandAuth_GetSize(byte msgType)
*/ */
static word16 TLSX_PostHandAuth_Write(byte* output, byte msgType) static word16 TLSX_PostHandAuth_Write(byte* output, byte msgType)
{ {
if (msgType == client_hello) { (void)output;
*output = 0;
return OPAQUE8_LEN; if (msgType == client_hello)
} return 0;
return SANITY_MSG_E; return SANITY_MSG_E;
} }
@ -7827,15 +7827,11 @@ static word16 TLSX_PostHandAuth_Write(byte* output, byte msgType)
static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length, static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length,
byte msgType) byte msgType)
{ {
byte len; (void)input;
if (msgType == client_hello) { if (msgType == client_hello) {
/* Ensure length byte exists. */ /* Ensure extension is empty. */
if (length < OPAQUE8_LEN) if (length != 0)
return BUFFER_E;
len = input[0];
if (length - OPAQUE8_LEN != len || len != 0)
return BUFFER_E; return BUFFER_E;
ssl->options.postHandshakeAuth = 1; ssl->options.postHandshakeAuth = 1;
@ -9811,7 +9807,7 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
case TLSX_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)) if (!IsAtLeastTLSv1_3(ssl->version))
break; break;

View File

@ -3202,16 +3202,6 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
/* This message is always encrypted so add encryption padding. */ /* This message is always encrypted so add encryption padding. */
*inOutIdx += ssl->keys.padSz; *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_LEAVE("DoTls13CertificateRequest", ret);
WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO); WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
@ -5833,7 +5823,15 @@ static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (*inOutIdx + size + ssl->keys.padSz > totalSz) if (*inOutIdx + size + ssl->keys.padSz > totalSz)
return BUFFER_E; 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 /* All the handshake messages have been received to calculate
* client and server finished keys. * client and server finished keys.
*/ */
@ -5939,7 +5937,15 @@ static int SendTls13Finished(WOLFSSL* ssl)
AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
/* make finished hashes */ /* 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; secret = ssl->keys.client_write_MAC_secret;
else { else {
/* All the handshake messages have been done to calculate client and /* All the handshake messages have been done to calculate client and
@ -6842,13 +6848,14 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
ssl->arrays->psk_keySz != 0) { ssl->arrays->psk_keySz != 0) {
WOLFSSL_MSG("CertificateRequset received while using PSK"); WOLFSSL_MSG("CertificateRequset received while using PSK");
return SANITY_MSG_E; return SANITY_MSG_E;
return SANITY_MSG_E;
} }
#endif #endif
#ifndef WOLFSSL_POST_HANDSHAKE_AUTH
if (ssl->msgsReceived.got_certificate_request) { if (ssl->msgsReceived.got_certificate_request) {
WOLFSSL_MSG("Duplicate CertificateRequest received"); WOLFSSL_MSG("Duplicate CertificateRequest received");
return DUPLICATE_MSG_E; return DUPLICATE_MSG_E;
} }
#endif
ssl->msgsReceived.got_certificate_request = 1; ssl->msgsReceived.got_certificate_request = 1;
break; break;
@ -6856,20 +6863,20 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
case certificate_verify: case certificate_verify:
#ifndef NO_WOLFSSL_CLIENT #ifndef NO_WOLFSSL_CLIENT
if (ssl->options.side == WOLFSSL_CLIENT_END && if (ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.serverState != SERVER_CERT_COMPLETE) { if (ssl->options.serverState != SERVER_CERT_COMPLETE) {
WOLFSSL_MSG("No Cert before CertVerify"); WOLFSSL_MSG("No Cert before CertVerify");
return OUT_OF_ORDER_E; 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 #endif
#ifndef NO_WOLFSSL_SERVER #ifndef NO_WOLFSSL_SERVER
if (ssl->options.side == WOLFSSL_SERVER_END) { if (ssl->options.side == WOLFSSL_SERVER_END) {
@ -7112,47 +7119,61 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->options.tls1_3) { if (ssl->options.tls1_3) {
/* Need to hash input message before deriving secrets. */ /* Need to hash input message before deriving secrets. */
#ifndef NO_WOLFSSL_CLIENT #ifndef NO_WOLFSSL_CLIENT
if (type == server_hello && ssl->options.side == WOLFSSL_CLIENT_END) { if (ssl->options.side == WOLFSSL_CLIENT_END) {
if ((ret = DeriveEarlySecret(ssl)) != 0) if (type == server_hello) {
return ret; if ((ret = DeriveEarlySecret(ssl)) != 0)
if ((ret = DeriveHandshakeSecret(ssl)) != 0) return ret;
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) { 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 (type == finished) {
if ((ret = DeriveMasterSecret(ssl)) != 0) if ((ret = DeriveMasterSecret(ssl)) != 0)
return ret; return ret;
#ifdef WOLFSSL_EARLY_DATA #ifdef WOLFSSL_EARLY_DATA
if ((ret = DeriveTls13Keys(ssl, traffic_key, if ((ret = DeriveTls13Keys(ssl, traffic_key,
ENCRYPT_AND_DECRYPT_SIDE, ENCRYPT_AND_DECRYPT_SIDE,
ssl->earlyData == no_early_data)) != 0) { ssl->earlyData == no_early_data)) != 0) {
return ret; return ret;
} }
#else #else
if ((ret = DeriveTls13Keys(ssl, traffic_key, if ((ret = DeriveTls13Keys(ssl, traffic_key,
ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { 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 #ifndef NO_WOLFSSL_SERVER
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #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); ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret);
if (ret != 0) if (ret != 0)
return ret; return ret;
@ -7475,14 +7496,9 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
FALL_THROUGH; FALL_THROUGH;
case FIRST_REPLY_THIRD: case FIRST_REPLY_THIRD:
#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) if ((ssl->error = SendTls13Finished(ssl)) != 0) {
if (!ssl->options.sendVerify || !ssl->options.postHandshakeAuth) WOLFSSL_ERROR(ssl->error);
#endif return WOLFSSL_FATAL_ERROR;
{
if ((ssl->error = SendTls13Finished(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
} }
WOLFSSL_MSG("sent: finished"); WOLFSSL_MSG("sent: finished");
@ -7783,11 +7799,16 @@ int wolfSSL_request_certificate(WOLFSSL* ssl)
certReqCtx->ctx = certReqCtx->next->ctx + 1; certReqCtx->ctx = certReqCtx->next->ctx + 1;
ssl->certReqCtx = certReqCtx; 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); ret = SendTls13CertificateRequest(ssl, &certReqCtx->ctx, certReqCtx->len);
if (ret == WANT_WRITE) if (ret == WANT_WRITE)
ret = WOLFSSL_ERROR_WANT_WRITE; ret = WOLFSSL_ERROR_WANT_WRITE;
else if (ret == 0) else if (ret == 0)
ret = WOLFSSL_SUCCESS; ret = WOLFSSL_SUCCESS;
return ret; return ret;
} }
#endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */ #endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */