TLS v1.3 support for Draft 23 and Draft 27

Draft 24: Second ClientHello usees version 0x0303 - no change.
Draft 25: The record layer header is now additional authentication data to
encryption.
Draft 26: Disallow SupportedVersion being used in ServerHello for
negotiating below TLS v1.3.
Draft 27: Older versions can be negotiated (by exclusion of 0x0304) in
SupportedVersion - no change.
This commit is contained in:
Sean Parkinson
2018-03-07 17:05:53 +10:00
parent f70351242b
commit bd53d7ba59
5 changed files with 81 additions and 27 deletions

View File

@ -307,6 +307,18 @@ then
fi fi
# TLS v1.3 Draft 23
AC_ARG_ENABLE([tls13-draft23],
[AS_HELP_STRING([--enable-tls13-draft23],[Enable wolfSSL TLS v1.3 Draft 23 (default: disabled)])],
[ ENABLED_TLS13_DRAFT23=$enableval ],
[ ENABLED_TLS13_DRAFT23=no ]
)
if test "$ENABLED_TLS13_DRAFT23" = "yes"
then
AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT_23 $AM_CFLAGS"
fi
# TLS v1.3 # TLS v1.3
AC_ARG_ENABLE([tls13], AC_ARG_ENABLE([tls13],
[AS_HELP_STRING([--enable-tls13],[Enable wolfSSL TLS v1.3 (default: disabled)])], [AS_HELP_STRING([--enable-tls13],[Enable wolfSSL TLS v1.3 (default: disabled)])],
@ -314,7 +326,7 @@ AC_ARG_ENABLE([tls13],
[ ENABLED_TLS13=no ] [ ENABLED_TLS13=no ]
) )
if test "$ENABLED_TLS13_DRAFT18" = "yes" || test "$ENABLED_TLS13_DRAFT22" = "yes" if test "$ENABLED_TLS13_DRAFT18" = "yes" || test "$ENABLED_TLS13_DRAFT22" = "yes" || test "$ENABLED_TLS13_DRAFT23" = "yes"
then then
ENABLED_TLS13="yes" ENABLED_TLS13="yes"
fi fi
@ -4311,6 +4323,8 @@ echo " * SSL version 3.0: $ENABLED_SSLV3"
echo " * TLS v1.0: $ENABLED_TLSV10" echo " * TLS v1.0: $ENABLED_TLSV10"
echo " * TLS v1.3: $ENABLED_TLS13" echo " * TLS v1.3: $ENABLED_TLS13"
echo " * TLS v1.3 Draft 18: $ENABLED_TLS13_DRAFT18" echo " * TLS v1.3 Draft 18: $ENABLED_TLS13_DRAFT18"
echo " * TLS v1.3 Draft 22: $ENABLED_TLS13_DRAFT22"
echo " * TLS v1.3 Draft 23: $ENABLED_TLS13_DRAFT23"
echo " * Post-handshake Auth: $ENABLED_TLS13_POST_AUTH" echo " * Post-handshake Auth: $ENABLED_TLS13_POST_AUTH"
echo " * Early Data: $ENABLED_TLS13_EARLY_DATA" echo " * Early Data: $ENABLED_TLS13_EARLY_DATA"
echo " * Send State in HRR Cookie: $ENABLED_SEND_HRR_COOKIE" echo " * Send State in HRR Cookie: $ENABLED_SEND_HRR_COOKIE"

View File

@ -12244,10 +12244,20 @@ int ProcessReply(WOLFSSL* ssl)
} }
else { else {
#ifdef WOLFSSL_TLS13 #ifdef WOLFSSL_TLS13
#if defined(WOLFSSL_TLS13_DRAFT_18) || \
defined(WOLFSSL_TLS13_DRAFT_22) || \
defined(WOLFSSL_TLS13_DRAFT_23)
ret = DecryptTls13(ssl, ret = DecryptTls13(ssl,
in->buffer + in->idx, in->buffer + in->idx,
in->buffer + in->idx, in->buffer + in->idx,
ssl->curSize); ssl->curSize, NULL, 0);
#else
ret = DecryptTls13(ssl,
in->buffer + in->idx,
in->buffer + in->idx,
ssl->curSize,
(byte*)&ssl->curRL, RECORD_HEADER_SZ);
#endif
#else #else
ret = DECRYPT_ERROR; ret = DECRYPT_ERROR;
#endif /* WOLFSSL_TLS13 */ #endif /* WOLFSSL_TLS13 */

View File

@ -4606,7 +4606,6 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input,
{ {
ProtocolVersion pv = ssl->ctx->method->version; ProtocolVersion pv = ssl->ctx->method->version;
int i; int i;
int ret = VERSION_ERROR;
int len; int len;
byte major, minor; byte major, minor;
@ -4660,7 +4659,6 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input,
TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS); TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS);
#endif #endif
} }
ret = 0;
break; break;
} }
} }
@ -4682,9 +4680,12 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input,
if (major != pv.major) if (major != pv.major)
return VERSION_ERROR; return VERSION_ERROR;
/* Can't downgrade with this extension below TLS v1.3. */
if (minor < TLSv1_3_MINOR)
return VERSION_ERROR;
/* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */ /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */
if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR && if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR) {
minor >= TLSv1_3_MINOR) {
/* Set minor version back to TLS v1.3+ */ /* Set minor version back to TLS v1.3+ */
ssl->version.minor = ssl->ctx->method->version.minor; ssl->version.minor = ssl->ctx->method->version.minor;
} }
@ -4704,14 +4705,12 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input,
/* Downgrade the version. */ /* Downgrade the version. */
ssl->version.minor = minor; ssl->version.minor = minor;
} }
ret = 0;
} }
#endif #endif
else else
return SANITY_MSG_E; return SANITY_MSG_E;
return ret; return 0;
} }
/* Sets a new SupportedVersions extension into the extension list. /* Sets a new SupportedVersions extension into the extension list.

View File

@ -1500,12 +1500,14 @@ static INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv,
* input The data to encrypt. * input The data to encrypt.
* sz The number of bytes to encrypt. * sz The number of bytes to encrypt.
* nonce The nonce to use with ChaCha20. * nonce The nonce to use with ChaCha20.
* aad The additional authentication data.
* aadSz The size of the addition authentication data.
* tag The authentication tag buffer. * tag The authentication tag buffer.
* returns 0 on success, otherwise failure. * returns 0 on success, otherwise failure.
*/ */
static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output,
const byte* input, word16 sz, byte* nonce, const byte* input, word16 sz, byte* nonce,
byte* tag) const byte* aad, word16 aadSz, byte* tag)
{ {
int ret = 0; int ret = 0;
byte poly[CHACHA20_256_KEY_SIZE]; byte poly[CHACHA20_256_KEY_SIZE];
@ -1534,8 +1536,8 @@ static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output,
if (ret != 0) if (ret != 0)
return ret; return ret;
/* Add authentication code of encrypted data to end. */ /* Add authentication code of encrypted data to end. */
ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, output, sz, tag, ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, output, sz,
POLY1305_AUTH_SZ); tag, POLY1305_AUTH_SZ);
return ret; return ret;
} }
@ -1546,13 +1548,15 @@ static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output,
* ssl The SSL/TLS object. * ssl The SSL/TLS object.
* output The buffer to write encrypted data and authentication tag into. * output The buffer to write encrypted data and authentication tag into.
* May be the same pointer as input. * May be the same pointer as input.
* input The data to encrypt. * input The record header and data to encrypt.
* sz The number of bytes to encrypt. * sz The number of bytes to encrypt.
* aad The additional authentication data.
* aadSz The size of the addition authentication data.
* asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto
* returns 0 on success, otherwise failure. * returns 0 on success, otherwise failure.
*/ */
static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
word16 sz, int asyncOkay) word16 sz, const byte* aad, word16 aadSz, int asyncOkay)
{ {
int ret = 0; int ret = 0;
word16 dataSz = sz - ssl->specs.aead_mac_size; word16 dataSz = sz - ssl->specs.aead_mac_size;
@ -1585,6 +1589,11 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
#ifdef WOLFSSL_DEBUG_TLS #ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Data to encrypt"); WOLFSSL_MSG("Data to encrypt");
WOLFSSL_BUFFER(input, dataSz); WOLFSSL_BUFFER(input, dataSz);
#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
!defined(WOLFSSL_TLS13_DRAFT_23)
WOLFSSL_MSG("Addition Authentication Data");
WOLFSSL_BUFFER(aad, aadSz);
#endif
#endif #endif
if (ssl->encrypt.nonce == NULL) if (ssl->encrypt.nonce == NULL)
@ -1617,7 +1626,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
nonceSz = AESGCM_NONCE_SZ; nonceSz = AESGCM_NONCE_SZ;
ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input,
dataSz, ssl->encrypt.nonce, nonceSz, dataSz, ssl->encrypt.nonce, nonceSz,
output + dataSz, macSz, NULL, 0); output + dataSz, macSz, aad, aadSz);
break; break;
#endif #endif
@ -1634,14 +1643,14 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
nonceSz = AESCCM_NONCE_SZ; nonceSz = AESCCM_NONCE_SZ;
ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input,
dataSz, ssl->encrypt.nonce, nonceSz, dataSz, ssl->encrypt.nonce, nonceSz,
output + dataSz, macSz, NULL, 0); output + dataSz, macSz, aad, aadSz);
break; break;
#endif #endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
case wolfssl_chacha: case wolfssl_chacha:
ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz,
ssl->encrypt.nonce, output + dataSz); ssl->encrypt.nonce, aad, aadSz, output + dataSz);
break; break;
#endif #endif
@ -1700,11 +1709,14 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
* input The data to decrypt. * input The data to decrypt.
* sz The number of bytes to decrypt. * sz The number of bytes to decrypt.
* nonce The nonce to use with ChaCha20. * nonce The nonce to use with ChaCha20.
* aad The additional authentication data.
* aadSz The size of the addition authentication data.
* tagIn The authentication tag data from packet. * tagIn The authentication tag data from packet.
* returns 0 on success, otherwise failure. * returns 0 on success, otherwise failure.
*/ */
static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output, static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output,
const byte* input, word16 sz, byte* nonce, const byte* input, word16 sz, byte* nonce,
const byte* aad, word16 aadSz,
const byte* tagIn) const byte* tagIn)
{ {
int ret; int ret;
@ -1729,8 +1741,8 @@ static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output,
if (ret != 0) if (ret != 0)
return ret; return ret;
/* Generate authentication tag for encrypted data. */ /* Generate authentication tag for encrypted data. */
if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, (byte*)input, sz, if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz,
tag, sizeof(tag))) != 0) { (byte*)input, sz, tag, sizeof(tag))) != 0) {
return ret; return ret;
} }
@ -1752,11 +1764,14 @@ static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output,
* ssl The SSL/TLS object. * ssl The SSL/TLS object.
* output The buffer to write decrypted data into. * output The buffer to write decrypted data into.
* May be the same pointer as input. * May be the same pointer as input.
* input The data to encrypt and authentication tag. * input The data to decrypt and authentication tag.
* sz The length of the encrypted data plus authentication tag. * sz The length of the encrypted data plus authentication tag.
* aad The additional authentication data.
* aadSz The size of the addition authentication data.
* returns 0 on success, otherwise failure. * returns 0 on success, otherwise failure.
*/ */
int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz,
const byte* aad, word16 aadSz)
{ {
int ret = 0; int ret = 0;
word16 dataSz = sz - ssl->specs.aead_mac_size; word16 dataSz = sz - ssl->specs.aead_mac_size;
@ -1797,6 +1812,11 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz)
#ifdef WOLFSSL_DEBUG_TLS #ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Data to decrypt"); WOLFSSL_MSG("Data to decrypt");
WOLFSSL_BUFFER(input, dataSz); WOLFSSL_BUFFER(input, dataSz);
#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \
!defined(WOLFSSL_TLS13_DRAFT_23)
WOLFSSL_MSG("Addition Authentication Data");
WOLFSSL_BUFFER(aad, aadSz);
#endif
WOLFSSL_MSG("Authentication tag"); WOLFSSL_MSG("Authentication tag");
WOLFSSL_BUFFER(input + dataSz, macSz); WOLFSSL_BUFFER(input + dataSz, macSz);
#endif #endif
@ -1831,7 +1851,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz)
nonceSz = AESGCM_NONCE_SZ; nonceSz = AESGCM_NONCE_SZ;
ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input, ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input,
dataSz, ssl->decrypt.nonce, nonceSz, dataSz, ssl->decrypt.nonce, nonceSz,
input + dataSz, macSz, NULL, 0); input + dataSz, macSz, aad, aadSz);
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_PENDING_E) { if (ret == WC_PENDING_E) {
ret = wolfSSL_AsyncPush(ssl, ret = wolfSSL_AsyncPush(ssl,
@ -1854,7 +1874,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz)
nonceSz = AESCCM_NONCE_SZ; nonceSz = AESCCM_NONCE_SZ;
ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input,
dataSz, ssl->decrypt.nonce, nonceSz, dataSz, ssl->decrypt.nonce, nonceSz,
input + dataSz, macSz, NULL, 0); input + dataSz, macSz, aad, aadSz);
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_PENDING_E) { if (ret == WC_PENDING_E) {
ret = wolfSSL_AsyncPush(ssl, ret = wolfSSL_AsyncPush(ssl,
@ -1867,7 +1887,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz)
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
case wolfssl_chacha: case wolfssl_chacha:
ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz, ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz,
ssl->decrypt.nonce, input + dataSz); ssl->decrypt.nonce, aad, aadSz, input + dataSz);
break; break;
#endif #endif
@ -2060,8 +2080,17 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
else else
#endif #endif
{ {
#if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) || \
defined(WOLFSSL_TLS13_DRAFT_23)
output += args->headerSz; output += args->headerSz;
ret = EncryptTls13(ssl, output, output, args->size, asyncOkay); ret = EncryptTls13(ssl, output, output, args->size, NULL, 0,
asyncOkay);
#else
const byte* aad = output;
output += args->headerSz;
ret = EncryptTls13(ssl, output, output, args->size, aad,
RECORD_HEADER_SZ, asyncOkay);
#endif
} }
break; break;
} }

View File

@ -1030,8 +1030,10 @@ enum Misc {
TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */ TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */
#elif defined(WOLFSSL_TLS13_DRAFT_22) #elif defined(WOLFSSL_TLS13_DRAFT_22)
TLS_DRAFT_MINOR = 0x16, /* Minor version number of TLS draft */ TLS_DRAFT_MINOR = 0x16, /* Minor version number of TLS draft */
#else #elif defined(WOLFSSL_TLS13_DRAFT_23)
TLS_DRAFT_MINOR = 0x17, /* Minor version number of TLS draft */ TLS_DRAFT_MINOR = 0x17, /* Minor version number of TLS draft */
#else
TLS_DRAFT_MINOR = 0x1b, /* Minor version number of TLS draft */
#endif #endif
OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */ OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */
INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */ INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */
@ -1506,7 +1508,7 @@ WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl);
#endif #endif
#ifdef WOLFSSL_TLS13 #ifdef WOLFSSL_TLS13
WOLFSSL_LOCAL int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, WOLFSSL_LOCAL int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
word16 sz); word16 sz, const byte* aad, word16 aadSz);
WOLFSSL_LOCAL int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, WOLFSSL_LOCAL int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input,
word32* inOutIdx, byte type, word32* inOutIdx, byte type,
word32 size, word32 totalSz); word32 size, word32 totalSz);