Updates from code review

pull/980/head
Sean Parkinson 2017-06-22 12:40:41 +10:00
parent decdf7ae8b
commit 08a0b98f52
3 changed files with 198 additions and 39 deletions

View File

@ -248,21 +248,55 @@ then
fi
# TLS v1.3 Draft 18
AC_ARG_ENABLE([tls13-draft18],
[AS_HELP_STRING([--enable-tls13-draft18],[Enable wolfSSL TLS v1.3 Draft 18 (default: disabled)])],
[ ENABLED_TLS13_DRAFT18=$enableval ],
[ ENABLED_TLS13_DRAFT18=no ]
)
if test "$ENABLED_TLS13_DRAFT18" = "yes"
then
AM_CFLAGS="-DWOLFSSL_TLS13_DRAFT18 $AM_CFLAGS"
fi
# TLS v1.3
AC_ARG_ENABLE([tls13],
[AS_HELP_STRING([--enable-tls13],[Enable wolfSSL TLS v1.3 (default: disabled)])],
[ ENABLED_TLS13=$enableval ],
[ ENABLED_TLS13=no ]
)
if test "$ENABLED_TLS13_DRAFT18" = "yes"
then
ENABLED_TLS13="yes"
fi
if test "$ENABLED_TLS13" = "yes"
then
AM_CFLAGS="-DWOLFSSL_TLS13 -DHAVE_TLS_EXTENSIONS -DHAVE_FFDHE_2048 $AM_CFLAGS"
AM_CFLAGS="-DWOLFSSL_TLS13 -DHAVE_TLS_EXTENSIONS -DHAVE_FFDHE_2048 $AM_CFLAGS"
fi
# check if TLS v1.3 was enabled for conditionally running tls13.test script
AM_CONDITIONAL([BUILD_TLS13], [test "x$ENABLED_TLS13" = "xyes"])
# Post-handshake Authentication
AC_ARG_ENABLE([postauth],
[AS_HELP_STRING([--enable-postauth],[Enable wolfSSL Post-handshake Authentication (default: disabled)])],
[ ENABLED_TLS13_POST_AUTH=$enableval ],
[ ENABLED_TLS13_POST_AUTH=no ]
)
if test "$ENABLED_TLS13_POST_AUTH" = "yes"
then
if test "x$ENABLED_TLS13" = "xno"
then
AC_MSG_ERROR([cannot enable postauth without enabling tls13.])
fi
AM_CFLAGS="-DWOLFSSL_POST_HANDSHAKE_AUTH $AM_CFLAGS"
fi
AC_ARG_ENABLE([rng],
[AS_HELP_STRING([--enable-rng],[Enable compiling and using RNG (default: enabled)])],
[ ENABLED_RNG=$enableval ],
@ -2329,10 +2363,10 @@ fi
# Early Data handshake in TLS v1.3 and above
AC_ARG_ENABLE([earlydata],
[AS_HELP_STRING([--enable-earlydata],[Enable Early Data handshake with wolfSSL TLS v1.3 (default: disabled)])],
[ ENABLED_EARLY_DATA=$enableval ],
[ ENABLED_EARLY_DATA=no ]
[ ENABLED_TLS13_EARLY_DATA=$enableval ],
[ ENABLED_TLS13_EARLY_DATA=no ]
)
if test "$ENABLED_EARLY_DATA" = "yes"
if test "$ENABLED_TLS13_EARLY_DATA" = "yes"
then
if test "x$ENABLED_TLS13" = "xno"
then
@ -3760,7 +3794,9 @@ echo " * SCTP: $ENABLED_SCTP"
echo " * Old TLS Versions: $ENABLED_OLD_TLS"
echo " * SSL version 3.0: $ENABLED_SSLV3"
echo " * TLS v1.3: $ENABLED_TLS13"
echo " * Early Data: $ENABLED_EARLY_DATA"
echo " * TLS v1.3 Draft 18: $ENABLED_TLS13_DRAFT18"
echo " * Post-handshake Auth: $ENABLED_TLS13_POST_AUTH"
echo " * Early Data: $ENABLED_TLS13_EARLY_DATA"
echo " * OCSP: $ENABLED_OCSP"
echo " * OCSP Stapling: $ENABLED_CERTIFICATE_STATUS_REQUEST"
echo " * OCSP Stapling v2: $ENABLED_CERTIFICATE_STATUS_REQUEST_V2"

View File

@ -1941,7 +1941,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
ClientRead(ssl, reply, sizeof(reply)-1, 1);
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (postHandAuth)
ClientWrite(ssl, msg, msgSz);
#endif

View File

@ -20,6 +20,22 @@
*/
/*
* WOLFSSL_TLS13_DRAFT_18
* Conform with Draft 18 of the TLS v1.3 specification.
* WOLFSSL_EARLY_DATA
* Allow 0-RTT Handshake using Early Data extensions and handshake message
* WOLFSSL_POST_HANDSHAKE_AUTH
* Allow TLS v1.3 code to perform post-handshake authentication of the
* client.
* WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
* Allow a NewSessionTicket message to be sent by server before Client's
* Finished message.
* See TLS v.13 specification, Section 4.6.1, Paragraph 4 (Note).
* TLS13_SUPPORTS_EXPORTERS
* Gaurd to compile out any code for exporter keys.
* Feature not supported yet.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
@ -210,16 +226,16 @@ static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
}
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Salt");
WOLFSSL_MSG(" Salt");
WOLFSSL_BUFFER(salt, saltLen);
WOLFSSL_MSG("IKM");
WOLFSSL_MSG(" IKM");
WOLFSSL_BUFFER(ikm, ikmLen);
#endif
ret = wc_HKDF_Extract(hash, salt, saltLen, ikm, ikmLen, prk);
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("PRK");
WOLFSSL_MSG(" PRK");
WOLFSSL_BUFFER(prk, len);
#endif
@ -268,16 +284,16 @@ static int HKDF_Expand_Label(byte* okm, word32 okmLen,
idx += infoLen;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("PRK");
WOLFSSL_MSG(" PRK");
WOLFSSL_BUFFER(prk, prkLen);
WOLFSSL_MSG("Info");
WOLFSSL_MSG(" Info");
WOLFSSL_BUFFER(data, idx);
#endif
ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("OKM");
WOLFSSL_MSG(" OKM");
WOLFSSL_BUFFER(okm, okmLen);
#endif
@ -548,7 +564,7 @@ static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key)
ssl->specs.mac_algorithm, 1);
}
#ifdef TLS13_SUPPORTS_EXPORTERS
#ifdef TLS13_SUPPORTS_EXPORTERS
#ifdef WOLFSSL_TLS13_DRAFT_18
/* The length of the early exporter label. */
#define EARLY_EXPORTER_LABEL_SZ 28
@ -575,7 +591,7 @@ static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key)
earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ,
ssl->specs.mac_algorithm, 1);
}
#endif
#endif
#endif
#ifdef WOLFSSL_TLS13_DRAFT_18
@ -1399,7 +1415,7 @@ static int RestartHandshakeHash(WOLFSSL* ssl)
ret = HashOutputRaw(ssl, header, sizeof(header));
if (ret != 0)
return ret;
return HashOutputRaw(ssl, hash, header[3]);
return HashOutputRaw(ssl, hash, header[MSG_HASH_LEN_OFFSET]);
}
#endif
@ -2678,9 +2694,9 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
int ret = 0;
#ifndef WOLFSSL_TLS13_DRAFT_18
Suites peerSuites;
#endif
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
CertReqCtx* certReqCtx;
#endif
#endif
WOLFSSL_ENTER("DoTls13CertificateRequest");
@ -2700,9 +2716,23 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
if (ssl->options.connectState < FINISHED_DONE && len > 0)
return BUFFER_ERROR;
#ifdef WOLFSSL_TLS13_DRAFT_18
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
/* CertReqCtx has one byte at end for context value.
* Increase size to handle other implementations sending more than one byte.
* That is, allocate extra space, over one byte, to hold the context value.
*/
certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx) + len - 1, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (certReqCtx == NULL)
return MEMORY_E;
certReqCtx->next = ssl->certReqCtx;
certReqCtx->len = len;
XMEMCPY(&certReqCtx->ctx, input + *inOutIdx, len);
ssl->certReqCtx = certReqCtx;
#endif
*inOutIdx += len;
#ifdef WOLFSSL_TLS13_DRAFT_18
/* Signature and hash algorithms. */
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
@ -2747,18 +2777,6 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
return BUFFER_ERROR;
*inOutIdx += len;
#else
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx) + len - 1, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (certReqCtx == NULL)
return MEMORY_E;
certReqCtx->next = ssl->certReqCtx;
certReqCtx->len = len;
XMEMCPY(&certReqCtx->ctx, input + *inOutIdx, len);
ssl->certReqCtx = certReqCtx;
#endif
*inOutIdx += len;
/* TODO: Add support for more extensions:
* signed_certificate_timestamp, certificate_authorities, oid_filters.
*/
@ -3486,8 +3504,6 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
WOLFSSL_ENTER("SendTls13CertificateRequest");
#ifdef WOLFSSL_TLS13_DRAFT_18
(void)reqCtx;
i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ;
reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz;
@ -3509,6 +3525,10 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
/* Certificate request context. */
output[i++] = reqCtxLen;
if (reqCtxLen != 0) {
XMEMCPY(output + i, reqCtx, reqCtxLen);
i += reqCtxLen;
}
/* supported hash/sig */
c16toa(ssl->suites->hashSigAlgoSz, &output[i]);
@ -5525,6 +5545,101 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input,
#ifndef NO_WOLFSSL_SERVER
#ifdef HAVE_SESSION_TICKET
#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
/* Offset of the MAC size in the finished message. */
#define FINISHED_MSG_SIZE_OFFSET 3
/* Calculate the resumption secret which includes the unseen client finished
* message.
*
* ssl The SSL/TLS object.
* retuns 0 on success, otherwise failure.
*/
static int ExpectedResumptionSecret(WOLFSSL* ssl)
{
int ret;
word32 finishedSz = 0;
byte mac[MAX_DIGEST_SIZE];
Digest digest;
static byte header[] = { 0x14, 0x00, 0x00, 0x00 };
/* Copy the running hash so we cna restore it after. */
switch (ssl->specs.mac_algorithm) {
#ifndef NO_SHA256
case sha256_mac:
ret = wc_Sha256Copy(&ssl->hsHashes->hashSha256, &digest.sha256);
if (ret != 0)
return ret;
break;
#endif
#ifdef WOLFSSL_SHA384
case sha384_mac:
ret = wc_Sha384Copy(&ssl->hsHashes->hashSha384, &digest.sha384);
if (ret != 0)
return ret;
break;
#endif
#ifdef WOLFSSL_SHA512
case sha512_mac:
ret = wc_Sha512Copy(&ssl->hsHashes->hashSha512, &digest.sha512);
if (ret != 0)
return ret;
break;
#endif
}
/* Generate the Client's Finished message and hash it. */
ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, mac,
&finishedSz);
if (ret != 0)
return ret;
header[FINISHED_MSG_SIZE_OFFSET] = finishedSz;
#ifdef WOLFSSL_EARLY_DATA
if (ssl->earlyData) {
static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 };
ret = HashInputRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData));
if (ret != 0)
return ret;
}
#endif
if ((ret = HashInputRaw(ssl, header, sizeof(header))) != 0)
return ret;
if ((ret = HashInputRaw(ssl, mac, finishedSz)) != 0)
return ret;
if ((ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret)) != 0)
return ret;
/* Restore the hash inline with currently seen messages. */
switch (ssl->specs.mac_algorithm) {
#ifndef NO_SHA256
case sha256_mac:
ret = wc_Sha256Copy(&digest.sha256, &ssl->hsHashes->hashSha256);
if (ret != 0)
return ret;
break;
#endif
#ifdef WOLFSSL_SHA384
case sha384_mac:
ret = wc_Sha384Copy(&digest.sha384, &ssl->hsHashes->hashSha384);
if (ret != 0)
return ret;
break;
#endif
#ifdef WOLFSSL_SHA512
case sha512_mac:
ret = wc_Sha512Copy(&digest.sha512, &ssl->hsHashes->hashSha384);
if (ret != 0)
return ret;
break;
#endif
}
return ret;
}
#endif
/* Send New Session Ticket handshake message.
* Message contains the information required to perform resumption.
*
@ -5542,6 +5657,13 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl)
WOLFSSL_ENTER("SendTls13NewSessionTicket");
#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
if (!ssl->msgsReceived.got_finished) {
if ((ret = ExpectedResumptionSecret(ssl)) != 0)
return ret;
}
#endif
if (!ssl->options.noTicketTls13) {
if ((ret = CreateTicket(ssl)) != 0)
return ret;
@ -5994,8 +6116,11 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
if (type == finished && ssl->options.side == WOLFSSL_SERVER_END)
DeriveResumptionSecret(ssl, ssl->session.masterSecret);
if (type == finished && ssl->options.side == WOLFSSL_SERVER_END) {
ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret);
if (ret != 0)
return ret;
}
#endif
}
@ -6477,7 +6602,6 @@ int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl)
{
if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
return BAD_FUNC_ARG;
return BAD_FUNC_ARG;
if (ssl->options.side == WOLFSSL_SERVER_END)
return SIDE_ERROR;
@ -6719,8 +6843,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
case ACCEPT_FINISHED_DONE :
#ifdef HAVE_SESSION_TICKET
#ifdef RESUMPTION_SECRET_CALCULATED_WITHOUT_CLIENT_FINISHED
/* TODO: [TLS13] Section 4.6.1 Note. */
#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
if (!ssl->options.resuming && !ssl->options.verifyPeer &&
!ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) {
if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) {
@ -6728,7 +6851,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
return SSL_FATAL_ERROR;
}
}
#endif
#endif
#endif /* HAVE_SESSION_TICKET */
ssl->options.acceptState = TICKET_SENT;
WOLFSSL_MSG("accept state TICKET_SENT");
@ -6747,11 +6870,11 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
case ACCEPT_SECOND_REPLY_DONE :
#ifdef HAVE_SESSION_TICKET
#ifdef RESUMPTION_SECRET_CALCULATED_WITHOUT_CLIENT_FINISHED
#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
if (!ssl->options.verifyPeer) {
}
else
#endif
#endif
if (!ssl->options.resuming &&
!ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) {
if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) {