diff --git a/configure.ac b/configure.ac index 2eaab4729..b1447f99e 100644 --- a/configure.ac +++ b/configure.ac @@ -307,6 +307,18 @@ then 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 AC_ARG_ENABLE([tls13], [AS_HELP_STRING([--enable-tls13],[Enable wolfSSL TLS v1.3 (default: disabled)])], @@ -314,7 +326,7 @@ AC_ARG_ENABLE([tls13], [ 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 ENABLED_TLS13="yes" fi @@ -4311,6 +4323,8 @@ echo " * SSL version 3.0: $ENABLED_SSLV3" echo " * TLS v1.0: $ENABLED_TLSV10" echo " * TLS v1.3: $ENABLED_TLS13" 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 " * Early Data: $ENABLED_TLS13_EARLY_DATA" echo " * Send State in HRR Cookie: $ENABLED_SEND_HRR_COOKIE" diff --git a/src/internal.c b/src/internal.c index c8e74fe46..5535c1d78 100644 --- a/src/internal.c +++ b/src/internal.c @@ -12244,10 +12244,20 @@ int ProcessReply(WOLFSSL* ssl) } else { #ifdef WOLFSSL_TLS13 + #if defined(WOLFSSL_TLS13_DRAFT_18) || \ + defined(WOLFSSL_TLS13_DRAFT_22) || \ + defined(WOLFSSL_TLS13_DRAFT_23) ret = DecryptTls13(ssl, 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 ret = DECRYPT_ERROR; #endif /* WOLFSSL_TLS13 */ diff --git a/src/tls.c b/src/tls.c index b22b6683f..e81ae0eb2 100644 --- a/src/tls.c +++ b/src/tls.c @@ -4606,7 +4606,6 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, { ProtocolVersion pv = ssl->ctx->method->version; int i; - int ret = VERSION_ERROR; int len; byte major, minor; @@ -4660,7 +4659,6 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS); #endif } - ret = 0; break; } } @@ -4682,9 +4680,12 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, if (major != pv.major) 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+. */ - if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR && - minor >= TLSv1_3_MINOR) { + if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR) { /* Set minor version back to TLS v1.3+ */ ssl->version.minor = ssl->ctx->method->version.minor; } @@ -4704,14 +4705,12 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, /* Downgrade the version. */ ssl->version.minor = minor; } - - ret = 0; } #endif else return SANITY_MSG_E; - return ret; + return 0; } /* Sets a new SupportedVersions extension into the extension list. diff --git a/src/tls13.c b/src/tls13.c index ae3339e10..1d34e55a5 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1500,12 +1500,14 @@ static INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv, * input The data to encrypt. * sz The number of bytes to encrypt. * 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. * returns 0 on success, otherwise failure. */ static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, byte* nonce, - byte* tag) + const byte* aad, word16 aadSz, byte* tag) { int ret = 0; byte poly[CHACHA20_256_KEY_SIZE]; @@ -1534,8 +1536,8 @@ static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, if (ret != 0) return ret; /* Add authentication code of encrypted data to end. */ - ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, output, sz, tag, - POLY1305_AUTH_SZ); + ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, output, sz, + tag, POLY1305_AUTH_SZ); return ret; } @@ -1546,13 +1548,15 @@ static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, * ssl The SSL/TLS object. * output The buffer to write encrypted data and authentication tag into. * 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. + * 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 * returns 0 on success, otherwise failure. */ 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; 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 WOLFSSL_MSG("Data to encrypt"); 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 if (ssl->encrypt.nonce == NULL) @@ -1617,7 +1626,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, nonceSz = AESGCM_NONCE_SZ; ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, dataSz, ssl->encrypt.nonce, nonceSz, - output + dataSz, macSz, NULL, 0); + output + dataSz, macSz, aad, aadSz); break; #endif @@ -1634,14 +1643,14 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, nonceSz = AESCCM_NONCE_SZ; ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, dataSz, ssl->encrypt.nonce, nonceSz, - output + dataSz, macSz, NULL, 0); + output + dataSz, macSz, aad, aadSz); break; #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case wolfssl_chacha: ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, - ssl->encrypt.nonce, output + dataSz); + ssl->encrypt.nonce, aad, aadSz, output + dataSz); break; #endif @@ -1700,11 +1709,14 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, * input The data to decrypt. * sz The number of bytes to decrypt. * 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. * returns 0 on success, otherwise failure. */ static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, byte* nonce, + const byte* aad, word16 aadSz, const byte* tagIn) { int ret; @@ -1729,8 +1741,8 @@ static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output, if (ret != 0) return ret; /* Generate authentication tag for encrypted data. */ - if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, (byte*)input, sz, - tag, sizeof(tag))) != 0) { + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, + (byte*)input, sz, tag, sizeof(tag))) != 0) { return ret; } @@ -1752,11 +1764,14 @@ static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output, * ssl The SSL/TLS object. * output The buffer to write decrypted data into. * 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. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. * 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; 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 WOLFSSL_MSG("Data to decrypt"); 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_BUFFER(input + dataSz, macSz); #endif @@ -1831,7 +1851,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) nonceSz = AESGCM_NONCE_SZ; ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input, dataSz, ssl->decrypt.nonce, nonceSz, - input + dataSz, macSz, NULL, 0); + input + dataSz, macSz, aad, aadSz); #ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { ret = wolfSSL_AsyncPush(ssl, @@ -1854,7 +1874,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) nonceSz = AESCCM_NONCE_SZ; ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, dataSz, ssl->decrypt.nonce, nonceSz, - input + dataSz, macSz, NULL, 0); + input + dataSz, macSz, aad, aadSz); #ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { 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) case wolfssl_chacha: ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz, - ssl->decrypt.nonce, input + dataSz); + ssl->decrypt.nonce, aad, aadSz, input + dataSz); break; #endif @@ -2060,8 +2080,17 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, else #endif { +#if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) || \ + defined(WOLFSSL_TLS13_DRAFT_23) 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; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 4e3bc0d80..0dcb8cda6 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1030,8 +1030,10 @@ enum Misc { TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */ #elif defined(WOLFSSL_TLS13_DRAFT_22) 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 */ +#else + TLS_DRAFT_MINOR = 0x1b, /* Minor version number of TLS draft */ #endif OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */ INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */ @@ -1506,7 +1508,7 @@ WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl); #endif #ifdef WOLFSSL_TLS13 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, word32* inOutIdx, byte type, word32 size, word32 totalSz);