forked from wolfSSL/wolfssl
@ -28,6 +28,7 @@
|
||||
#define WOLFSSL_RIPEMD
|
||||
#define WOLFSSL_SHA512
|
||||
#define NO_PSK
|
||||
#define HAVE_EXTENDED_MASTER
|
||||
#define WOLFSSL_SNIFFER
|
||||
#else
|
||||
/* The servers and clients */
|
||||
|
13
configure.ac
13
configure.ac
@ -1975,6 +1975,18 @@ then
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SESSION_TICKET"
|
||||
fi
|
||||
|
||||
# Extended Master Secret Extension
|
||||
AC_ARG_ENABLE([extended-master],
|
||||
[AS_HELP_STRING([--enable-extended-master],[Enable Extended Master Secret (default: enabled)])],
|
||||
[ ENABLED_EXTENDED_MASTER=$enableval ],
|
||||
[ ENABLED_EXTENDED_MASTER=yes ]
|
||||
)
|
||||
|
||||
if test "x$ENABLED_EXTENDED_MASTER" = "xyes"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_EXTENDED_MASTER"
|
||||
fi
|
||||
|
||||
# TLS Extensions
|
||||
AC_ARG_ENABLE([tlsx],
|
||||
[ --enable-tlsx Enable all TLS Extensions (default: disabled)],
|
||||
@ -3217,6 +3229,7 @@ echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT"
|
||||
echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC"
|
||||
echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES"
|
||||
echo " * Session Ticket: $ENABLED_SESSION_TICKET"
|
||||
echo " * Extended Master Secret: $ENABLED_EXTENDED_MASTER"
|
||||
echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION"
|
||||
echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION"
|
||||
echo " * All TLS Extensions: $ENABLED_TLSX"
|
||||
|
@ -494,6 +494,9 @@ static void Usage(void)
|
||||
#ifdef HAVE_TRUNCATED_HMAC
|
||||
printf("-T Use Truncated HMAC\n");
|
||||
#endif
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
printf("-n Disable Extended Master Secret\n");
|
||||
#endif
|
||||
#ifdef HAVE_OCSP
|
||||
printf("-o Perform OCSP lookup on peer certificate\n");
|
||||
printf("-O <url> Perform OCSP lookup using <url> as responder\n");
|
||||
@ -609,6 +612,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
|
||||
byte statusRequest = 0;
|
||||
#endif
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
byte disableExtMasterSecret = 0;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
@ -651,7 +657,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
|
||||
#ifndef WOLFSSL_VXWORKS
|
||||
while ((ch = mygetopt(argc, argv,
|
||||
"?gdeDuGsmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:q:"))
|
||||
"?gdeDuGsmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:TnoO:aB:W:E:M:q:"))
|
||||
!= -1) {
|
||||
switch (ch) {
|
||||
case '?' :
|
||||
@ -857,6 +863,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'n' :
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
disableExtMasterSecret = 1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'W' :
|
||||
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
|
||||
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
|
||||
@ -1233,6 +1245,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS)
|
||||
err_sys("UseSessionTicket failed");
|
||||
#endif
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (disableExtMasterSecret)
|
||||
if (wolfSSL_CTX_DisableExtendedMasterSecret(ctx) != SSL_SUCCESS)
|
||||
err_sys("DisableExtendedMasterSecret failed");
|
||||
#endif
|
||||
|
||||
if (benchmark) {
|
||||
((func_args*)args)->return_code =
|
||||
@ -1555,6 +1572,32 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
||||
wolfSSL_set_SessionTicket_cb(sslResume, sessionTicketCB,
|
||||
(void*)"resumed session");
|
||||
#endif
|
||||
#ifdef HAVE_SUPPORTED_CURVES /* add curves to supported curves extension */
|
||||
if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP256R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp256r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP384R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp384r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP521R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp521r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP224R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp224r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP192R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp192r1");
|
||||
}
|
||||
if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP160R1)
|
||||
!= SSL_SUCCESS) {
|
||||
err_sys("unable to set curve secp160r1");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WOLFSSL_CALLBACKS
|
||||
if (nonBlocking) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
# need a unique resume port since may run the same time as testsuite
|
||||
# use server port zero hack to get one
|
||||
resume_string="reused"
|
||||
ems_string="Extended\ Master\ Secret"
|
||||
resume_port=0
|
||||
no_pid=-1
|
||||
server_pid=$no_pid
|
||||
@ -41,57 +42,72 @@ do_trap() {
|
||||
exit -1
|
||||
}
|
||||
|
||||
do_test() {
|
||||
echo -e "\nStarting example server for resume test...\n"
|
||||
|
||||
remove_ready_file
|
||||
./examples/server/server -r -R $ready_file -p $resume_port &
|
||||
server_pid=$!
|
||||
|
||||
while [ ! -s $ready_file -a "$counter" -lt 20 ]; do
|
||||
echo -e "waiting for ready file..."
|
||||
sleep 0.1
|
||||
counter=$((counter+ 1))
|
||||
done
|
||||
|
||||
if test -e $ready_file; then
|
||||
echo -e "found ready file, starting client..."
|
||||
else
|
||||
echo -e "NO ready file ending test..."
|
||||
do_cleanup
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# get created port 0 ephemeral port
|
||||
resume_port=`cat $ready_file`
|
||||
|
||||
capture_out=$(./examples/client/client $1 -r -p $resume_port 2>&1)
|
||||
client_result=$?
|
||||
|
||||
if [ $client_result != 0 ]
|
||||
then
|
||||
echo -e "client failed!"
|
||||
do_cleanup
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wait $server_pid
|
||||
server_result=$?
|
||||
remove_ready_file
|
||||
|
||||
if [ $server_result != 0 ]
|
||||
then
|
||||
echo -e "client failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$capture_out" in
|
||||
*$resume_string*)
|
||||
echo "resumed session" ;;
|
||||
*)
|
||||
echo "did NOT resume session as expected"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
trap do_trap INT TERM
|
||||
|
||||
echo -e "\nStarting example server for resume test...\n"
|
||||
do_test
|
||||
|
||||
remove_ready_file
|
||||
./examples/server/server -r -R $ready_file -p $resume_port &
|
||||
server_pid=$!
|
||||
|
||||
while [ ! -s $ready_file -a "$counter" -lt 20 ]; do
|
||||
echo -e "waiting for ready file..."
|
||||
sleep 0.1
|
||||
counter=$((counter+ 1))
|
||||
done
|
||||
|
||||
if test -e $ready_file; then
|
||||
echo -e "found ready file, starting client..."
|
||||
else
|
||||
echo -e "NO ready file ending test..."
|
||||
do_cleanup
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# get created port 0 ephemeral port
|
||||
resume_port=`cat $ready_file`
|
||||
|
||||
capture_out=$(./examples/client/client -r -p $resume_port 2>&1)
|
||||
client_result=$?
|
||||
|
||||
if [ $client_result != 0 ]
|
||||
then
|
||||
echo -e "client failed!"
|
||||
do_cleanup
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wait $server_pid
|
||||
server_result=$?
|
||||
remove_ready_file
|
||||
|
||||
if [ $server_result != 0 ]
|
||||
then
|
||||
echo -e "client failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$capture_out" in
|
||||
*$resume_string*)
|
||||
echo "resumed session" ;;
|
||||
# Check the client for the extended master secret disable option. If
|
||||
# present we need to run the test twice.
|
||||
options_check=`./examples/client/client -?`
|
||||
case "$options_check" in
|
||||
*$ems_string*)
|
||||
echo -e "\nRepeating resume test without extended master secret..."
|
||||
do_test -n ;;
|
||||
*)
|
||||
echo "did NOT resume session as expected"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
196
src/internal.c
196
src/internal.c
@ -1401,6 +1401,20 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT)
|
||||
if (method->side == WOLFSSL_CLIENT_END) {
|
||||
if ((method->version.major == SSLv3_MAJOR) &&
|
||||
(method->version.minor >= TLSv1_MINOR)) {
|
||||
|
||||
ctx->haveEMS = 1;
|
||||
}
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (method->version.major == DTLS_MAJOR)
|
||||
ctx->haveEMS = 1;
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
}
|
||||
#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */
|
||||
|
||||
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
|
||||
ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT;
|
||||
#endif
|
||||
@ -3375,6 +3389,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
|
||||
ssl->cipher.ssl = ssl;
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
ssl->options.haveEMS = ctx->haveEMS;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
#ifdef HAVE_MAX_FRAGMENT
|
||||
ssl->max_fragment = MAX_RECORD_SIZE;
|
||||
@ -11435,6 +11453,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
|
||||
case CTX_INIT_MUTEX_E:
|
||||
return "Initialize ctx mutex error";
|
||||
|
||||
case EXT_MASTER_SECRET_NEEDED_E:
|
||||
return "Extended Master Secret must be enabled to resume EMS session";
|
||||
|
||||
default :
|
||||
return "unknown error number";
|
||||
}
|
||||
@ -12681,6 +12702,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
|
||||
? ssl->session.sessionIDSz
|
||||
: 0;
|
||||
int ret;
|
||||
word16 extSz = 0;
|
||||
|
||||
if (ssl->suites == NULL) {
|
||||
WOLFSSL_MSG("Bad suites pointer in SendClientHello");
|
||||
@ -12714,11 +12736,19 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
|
||||
if (QSH_Init(ssl) != 0)
|
||||
return MEMORY_E;
|
||||
#endif
|
||||
length += TLSX_GetRequestSize(ssl);
|
||||
extSz = TLSX_GetRequestSize(ssl);
|
||||
if (extSz != 0)
|
||||
length += extSz;
|
||||
#else
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) {
|
||||
length += ssl->suites->hashSigAlgoSz + HELLO_EXT_SZ;
|
||||
}
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
|
||||
extSz += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ
|
||||
+ ssl->suites->hashSigAlgoSz;
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (ssl->options.haveEMS)
|
||||
extSz += HELLO_EXT_SZ;
|
||||
#endif
|
||||
if (extSz != 0)
|
||||
length += extSz + HELLO_EXT_SZ_SZ;
|
||||
#endif
|
||||
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
|
||||
|
||||
@ -12803,24 +12833,36 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
|
||||
|
||||
(void)idx; /* suppress analyzer warning, keep idx current */
|
||||
#else
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
|
||||
{
|
||||
int i;
|
||||
/* add in the extensions length */
|
||||
c16toa((word16)(HELLO_EXT_LEN + ssl->suites->hashSigAlgoSz),
|
||||
output + idx);
|
||||
idx += 2;
|
||||
if (extSz != 0) {
|
||||
c16toa(extSz, output + idx);
|
||||
idx += HELLO_EXT_SZ_SZ;
|
||||
|
||||
c16toa(HELLO_EXT_SIG_ALGO, output + idx);
|
||||
idx += 2;
|
||||
c16toa((word16)(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz),
|
||||
output+idx);
|
||||
idx += 2;
|
||||
c16toa(ssl->suites->hashSigAlgoSz, output + idx);
|
||||
idx += 2;
|
||||
for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) {
|
||||
output[idx] = ssl->suites->hashSigAlgo[i];
|
||||
if (IsAtLeastTLSv1_2(ssl)) {
|
||||
if (ssl->suites->hashSigAlgoSz) {
|
||||
int i;
|
||||
/* extension type */
|
||||
c16toa(HELLO_EXT_SIG_ALGO, output + idx);
|
||||
idx += HELLO_EXT_TYPE_SZ;
|
||||
/* extension data length */
|
||||
c16toa(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz,
|
||||
output + idx);
|
||||
idx += HELLO_EXT_SZ_SZ;
|
||||
/* sig algos length */
|
||||
c16toa(ssl->suites->hashSigAlgoSz, output + idx);
|
||||
idx += HELLO_EXT_SIGALGO_SZ;
|
||||
for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, idx++) {
|
||||
output[idx] = ssl->suites->hashSigAlgo[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (ssl->options.haveEMS) {
|
||||
c16toa(HELLO_EXT_EXTMS, output + idx);
|
||||
idx += HELLO_EXT_TYPE_SZ;
|
||||
c16toa(0, output + idx);
|
||||
idx += HELLO_EXT_SZ_SZ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -13063,9 +13105,8 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
|
||||
|
||||
*inOutIdx = i;
|
||||
|
||||
|
||||
if ( (i - begin) < helloSz) {
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
if ( (i - begin) < helloSz) {
|
||||
if (TLSX_SupportExtensions(ssl)) {
|
||||
int ret = 0;
|
||||
word16 totalExtSz;
|
||||
@ -13087,9 +13128,70 @@ static void PickHashSigAlgo(WOLFSSL* ssl,
|
||||
*inOutIdx = i;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
*inOutIdx = begin + helloSz; /* skip extensions */
|
||||
}
|
||||
else
|
||||
ssl->options.haveEMS = 0; /* If no extensions, no EMS */
|
||||
#else
|
||||
{
|
||||
int allowExt = 0;
|
||||
byte pendingEMS = 0;
|
||||
|
||||
if ( (i - begin) < helloSz) {
|
||||
if (ssl->version.major == SSLv3_MAJOR &&
|
||||
ssl->version.minor >= TLSv1_MINOR) {
|
||||
|
||||
allowExt = 1;
|
||||
}
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->version.major == DTLS_MAJOR)
|
||||
allowExt = 1;
|
||||
#endif
|
||||
|
||||
if (allowExt) {
|
||||
word16 totalExtSz;
|
||||
|
||||
if ((i - begin) + OPAQUE16_LEN > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
ato16(&input[i], &totalExtSz);
|
||||
i += OPAQUE16_LEN;
|
||||
|
||||
if ((i - begin) + totalExtSz > helloSz)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
while (totalExtSz) {
|
||||
word16 extId, extSz;
|
||||
|
||||
if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
ato16(&input[i], &extId);
|
||||
i += OPAQUE16_LEN;
|
||||
ato16(&input[i], &extSz);
|
||||
i += OPAQUE16_LEN;
|
||||
|
||||
if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
if (extId == HELLO_EXT_EXTMS)
|
||||
pendingEMS = 1;
|
||||
else
|
||||
i += extSz;
|
||||
|
||||
totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
|
||||
}
|
||||
|
||||
*inOutIdx = i;
|
||||
}
|
||||
else
|
||||
*inOutIdx = begin + helloSz; /* skip extensions */
|
||||
}
|
||||
|
||||
if (!pendingEMS && ssl->options.haveEMS)
|
||||
ssl->options.haveEMS = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
ssl->options.serverState = SERVER_HELLO_COMPLETE;
|
||||
|
||||
@ -15984,6 +16086,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */
|
||||
}
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
#else
|
||||
if (ssl->options.haveEMS) {
|
||||
length += HELLO_EXT_SZ_SZ + HELLO_EXT_SZ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check for avalaible size */
|
||||
@ -16057,6 +16163,20 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
/* last, extensions */
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
TLSX_WriteResponse(ssl, output + idx);
|
||||
#else
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (ssl->options.haveEMS) {
|
||||
c16toa(HELLO_EXT_SZ, output + idx);
|
||||
idx += HELLO_EXT_SZ_SZ;
|
||||
|
||||
c16toa(HELLO_EXT_EXTMS, output + idx);
|
||||
idx += HELLO_EXT_TYPE_SZ;
|
||||
c16toa(0, output + idx);
|
||||
/*idx += HELLO_EXT_SZ_SZ;*/
|
||||
/* idx is not used after this point. uncomment the line above
|
||||
* if adding any more extentions in the future. */
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ssl->buffers.outputBuffer.length += sendSz;
|
||||
@ -18176,6 +18296,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
if (clSuites.hashSigAlgoSz > HELLO_EXT_SIGALGO_MAX)
|
||||
clSuites.hashSigAlgoSz = HELLO_EXT_SIGALGO_MAX;
|
||||
}
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
else if (extId == HELLO_EXT_EXTMS)
|
||||
ssl->options.haveEMS = 1;
|
||||
#endif
|
||||
else
|
||||
i += extSz;
|
||||
|
||||
@ -18209,6 +18333,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
WOLFSSL_MSG("Session lookup for resume failed");
|
||||
ssl->options.resuming = 0;
|
||||
}
|
||||
else if (session->haveEMS != ssl->options.haveEMS) {
|
||||
/* RFC 7627, 5.3, server-side */
|
||||
/* if old sess didn't have EMS, but new does, full handshake */
|
||||
if (!session->haveEMS && ssl->options.haveEMS) {
|
||||
WOLFSSL_MSG("Attempting to resume a session that didn't "
|
||||
"use EMS with a new session with EMS. Do full "
|
||||
"handshake.");
|
||||
ssl->options.resuming = 0;
|
||||
}
|
||||
/* if old sess used EMS, but new doesn't, MUST abort */
|
||||
else if (session->haveEMS && !ssl->options.haveEMS) {
|
||||
WOLFSSL_MSG("Trying to resume a session with EMS without "
|
||||
"using EMS");
|
||||
return EXT_MASTER_SECRET_NEEDED_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (MatchSuite(ssl, &clSuites) < 0) {
|
||||
WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
|
||||
@ -18621,6 +18761,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
byte suite[SUITE_LEN]; /* cipher suite when created */
|
||||
byte msecret[SECRET_LEN]; /* master secret */
|
||||
word32 timestamp; /* born on */
|
||||
word16 haveEMS; /* have extended master secret */
|
||||
} InternalTicket;
|
||||
|
||||
/* fit within SESSION_TICKET_LEN */
|
||||
@ -18642,6 +18783,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
int ret;
|
||||
byte zeros[WOLFSSL_TICKET_MAC_SZ]; /* biggest cmp size */
|
||||
|
||||
XMEMSET(&it, 0, sizeof(it));
|
||||
|
||||
/* build internal */
|
||||
it.pv.major = ssl->version.major;
|
||||
it.pv.minor = ssl->version.minor;
|
||||
@ -18651,6 +18794,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
|
||||
XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN);
|
||||
c32toa(LowResTimer(), (byte*)&it.timestamp);
|
||||
it.haveEMS = ssl->options.haveEMS;
|
||||
|
||||
/* build external */
|
||||
XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket));
|
||||
@ -18742,8 +18886,12 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
}
|
||||
|
||||
/* get master secret */
|
||||
if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE)
|
||||
if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) {
|
||||
XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
|
||||
/* Copy the haveExtendedMasterSecret property from the ticket to
|
||||
* the saved session, so the property may be checked later. */
|
||||
ssl->session.haveEMS = it->haveEMS;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
241
src/sniffer.c
241
src/sniffer.c
@ -90,6 +90,7 @@ enum {
|
||||
EXT_TYPE_SZ = 2, /* Extension length */
|
||||
MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
|
||||
MTU_EXTRA, /* Max input sz of reassembly */
|
||||
EXT_MASTER_SECRET = 0x17, /* Extended Master Secret Extension ID */
|
||||
TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */
|
||||
};
|
||||
|
||||
@ -253,7 +254,8 @@ static const char* const msgTable[] =
|
||||
"Clear ACK Fault",
|
||||
|
||||
/* 81 */
|
||||
"Bad Decrypt Size"
|
||||
"Bad Decrypt Size",
|
||||
"Extended Master Secret Hash Error"
|
||||
};
|
||||
|
||||
|
||||
@ -329,6 +331,9 @@ typedef struct Flags {
|
||||
byte srvAckFault; /* server acked unseen data from client */
|
||||
byte cliSkipPartial; /* client skips partial data to catch up */
|
||||
byte srvSkipPartial; /* server skips partial data to catch up */
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
byte expectEms; /* expect extended master secret */
|
||||
#endif
|
||||
} Flags;
|
||||
|
||||
|
||||
@ -341,6 +346,24 @@ typedef struct FinCaputre {
|
||||
} FinCaputre;
|
||||
|
||||
|
||||
typedef struct HsHashes {
|
||||
#ifndef NO_OLD_TLS
|
||||
#ifndef NO_SHA
|
||||
Sha hashSha;
|
||||
#endif
|
||||
#ifndef NO_MD5
|
||||
Md5 hashMd5;
|
||||
#endif
|
||||
#endif
|
||||
#ifndef NO_SHA256
|
||||
Sha256 hashSha256;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
Sha384 hashSha384;
|
||||
#endif
|
||||
} HsHashes;
|
||||
|
||||
|
||||
/* Sniffer Session holds info for each client/server SSL/TLS session */
|
||||
typedef struct SnifferSession {
|
||||
SnifferServer* context; /* server context */
|
||||
@ -363,6 +386,9 @@ typedef struct SnifferSession {
|
||||
word32 srvReassemblyMemory; /* server packet memory used */
|
||||
struct SnifferSession* next; /* for hash table list */
|
||||
byte* ticketID; /* mac ID of session ticket */
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
HsHashes* hash;
|
||||
#endif
|
||||
} SnifferSession;
|
||||
|
||||
|
||||
@ -483,6 +509,9 @@ static void FreeSnifferSession(SnifferSession* session)
|
||||
FreePacketList(session->srvReassemblyList);
|
||||
|
||||
free(session->ticketID);
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
free(session->hash);
|
||||
#endif
|
||||
}
|
||||
free(session);
|
||||
}
|
||||
@ -533,6 +562,91 @@ void ssl_FreeSniffer(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
|
||||
static int HashInit(HsHashes* hash)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
XMEMSET(hash, 0, sizeof(HsHashes));
|
||||
|
||||
#ifndef NO_OLD_TLS
|
||||
#ifndef NO_SHA
|
||||
if (ret == 0)
|
||||
ret = wc_InitSha(&hash->hashSha);
|
||||
#endif
|
||||
#ifndef NO_MD5
|
||||
if (ret == 0)
|
||||
wc_InitMd5(&hash->hashMd5);
|
||||
#endif
|
||||
#endif
|
||||
#ifndef NO_SHA256
|
||||
if (ret == 0)
|
||||
ret = wc_InitSha256(&hash->hashSha256);
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
if (ret == 0)
|
||||
ret = wc_InitSha384(&hash->hashSha384);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int HashUpdate(HsHashes* hash, const byte* input, int sz)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
input -= HANDSHAKE_HEADER_SZ;
|
||||
sz += HANDSHAKE_HEADER_SZ;
|
||||
|
||||
#ifndef NO_OLD_TLS
|
||||
#ifndef NO_SHA
|
||||
if (ret == 0)
|
||||
ret = wc_ShaUpdate(&hash->hashSha, input, sz);
|
||||
#endif
|
||||
#ifndef NO_MD5
|
||||
if (ret == 0)
|
||||
wc_Md5Update(&hash->hashMd5, input, sz);
|
||||
#endif
|
||||
#endif
|
||||
#ifndef NO_SHA256
|
||||
if (ret == 0)
|
||||
ret = wc_Sha256Update(&hash->hashSha256, input, sz);
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
if (ret == 0)
|
||||
ret = wc_Sha384Update(&hash->hashSha384, input, sz);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int HashCopy(HS_Hashes* d, HsHashes* s)
|
||||
{
|
||||
#ifndef NO_OLD_TLS
|
||||
#ifndef NO_SHA
|
||||
XMEMCPY(&d->hashSha, &s->hashSha, sizeof(Sha));
|
||||
#endif
|
||||
#ifndef NO_MD5
|
||||
XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(Md5));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_SHA256
|
||||
XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(Sha256));
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(Sha384));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Initialize a SnifferServer */
|
||||
static void InitSnifferServer(SnifferServer* sniffer)
|
||||
{
|
||||
@ -563,6 +677,9 @@ static void InitFlags(Flags* flags)
|
||||
flags->srvAckFault = 0;
|
||||
flags->cliSkipPartial = 0;
|
||||
flags->srvSkipPartial = 0;
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
flags->expectEms = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -600,6 +717,9 @@ static void InitSession(SnifferSession* session)
|
||||
|
||||
InitFlags(&session->flags);
|
||||
InitFinCapture(&session->finCaputre);
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
session->hash = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1483,13 +1603,17 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
|
||||
|
||||
|
||||
/* Process Server Hello */
|
||||
static int ProcessServerHello(const byte* input, int* sslBytes,
|
||||
static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
|
||||
SnifferSession* session, char* error)
|
||||
{
|
||||
ProtocolVersion pv;
|
||||
byte b;
|
||||
int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
|
||||
int doResume = 0;
|
||||
int initialBytes = *sslBytes;
|
||||
|
||||
(void)msgSz;
|
||||
(void)initialBytes;
|
||||
|
||||
/* make sure we didn't miss ClientHello */
|
||||
if (session->flags.clientHello == 0) {
|
||||
@ -1548,6 +1672,62 @@ static int ProcessServerHello(const byte* input, int* sslBytes,
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
/* extensions */
|
||||
if ((initialBytes - *sslBytes) < msgSz) {
|
||||
word16 len;
|
||||
|
||||
/* skip extensions until extended master secret */
|
||||
/* make sure can read len */
|
||||
if (SUITE_LEN > *sslBytes) {
|
||||
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
len = (word16)((input[0] << 8) | input[1]);
|
||||
input += SUITE_LEN;
|
||||
*sslBytes -= SUITE_LEN;
|
||||
/* make sure can read through all extensions */
|
||||
if (len > *sslBytes) {
|
||||
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
|
||||
byte extType[EXT_TYPE_SZ];
|
||||
word16 extLen;
|
||||
|
||||
extType[0] = input[0];
|
||||
extType[1] = input[1];
|
||||
input += EXT_TYPE_SZ;
|
||||
*sslBytes -= EXT_TYPE_SZ;
|
||||
|
||||
extLen = (word16)((input[0] << 8) | input[1]);
|
||||
input += LENGTH_SZ;
|
||||
*sslBytes -= LENGTH_SZ;
|
||||
|
||||
/* make sure can read through individual extension */
|
||||
if (extLen > *sslBytes) {
|
||||
SetError(SERVER_HELLO_INPUT_STR, error, session,
|
||||
FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) {
|
||||
session->flags.expectEms = 1;
|
||||
}
|
||||
|
||||
input += extLen;
|
||||
*sslBytes -= extLen;
|
||||
len -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
|
||||
}
|
||||
}
|
||||
|
||||
if (!session->flags.expectEms) {
|
||||
free(session->hash);
|
||||
session->hash = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (session->sslServer->options.haveSessionId &&
|
||||
XMEMCMP(session->sslServer->arrays->sessionID,
|
||||
session->sslClient->arrays->sessionID, ID_LEN) == 0)
|
||||
@ -1758,7 +1938,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (len > EXT_TYPE_SZ + LENGTH_SZ) {
|
||||
while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
|
||||
byte extType[EXT_TYPE_SZ];
|
||||
word16 extLen;
|
||||
|
||||
@ -1883,6 +2063,16 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (session->hash) {
|
||||
if (HashUpdate(session->hash, input, size) != 0) {
|
||||
SetError(EXTENDED_MASTER_HASH_STR, error,
|
||||
session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
case hello_verify_request:
|
||||
Trace(GOT_HELLO_VERIFY_STR);
|
||||
@ -1896,7 +2086,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
||||
break;
|
||||
case server_hello:
|
||||
Trace(GOT_SERVER_HELLO_STR);
|
||||
ret = ProcessServerHello(input, sslBytes, session, error);
|
||||
ret = ProcessServerHello(size, input, sslBytes, session, error);
|
||||
break;
|
||||
case certificate_request:
|
||||
Trace(GOT_CERT_REQ_STR);
|
||||
@ -1923,7 +2113,32 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
||||
break;
|
||||
case client_key_exchange:
|
||||
Trace(GOT_CLIENT_KEY_EX_STR);
|
||||
ret = ProcessClientKeyExchange(input, sslBytes, session, error);
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (session->flags.expectEms && session->hash != NULL) {
|
||||
if (HashCopy(session->sslServer->hsHashes,
|
||||
session->hash) == 0 &&
|
||||
HashCopy(session->sslClient->hsHashes,
|
||||
session->hash) == 0) {
|
||||
|
||||
session->sslServer->options.haveEMS = 1;
|
||||
session->sslClient->options.haveEMS = 1;
|
||||
}
|
||||
else {
|
||||
SetError(EXTENDED_MASTER_HASH_STR, error,
|
||||
session, FATAL_ERROR_STATE);
|
||||
ret = -1;
|
||||
}
|
||||
XMEMSET(session->hash, 0, sizeof(HsHashes));
|
||||
free(session->hash);
|
||||
session->hash = NULL;
|
||||
}
|
||||
else {
|
||||
session->sslServer->options.haveEMS = 0;
|
||||
session->sslClient->options.haveEMS = 0;
|
||||
}
|
||||
#endif
|
||||
if (ret == 0)
|
||||
ret = ProcessClientKeyExchange(input, sslBytes, session, error);
|
||||
break;
|
||||
case certificate_verify:
|
||||
Trace(GOT_CERT_VER_STR);
|
||||
@ -2135,6 +2350,22 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
|
||||
return 0;
|
||||
}
|
||||
InitSession(session);
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
{
|
||||
HsHashes* newHash = (HsHashes*)malloc(sizeof(HsHashes));
|
||||
if (newHash == NULL) {
|
||||
SetError(MEMORY_STR, error, NULL, 0);
|
||||
free(session);
|
||||
return 0;
|
||||
}
|
||||
if (HashInit(newHash) != 0) {
|
||||
SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0);
|
||||
free(session);
|
||||
return 0;
|
||||
}
|
||||
session->hash = newHash;
|
||||
}
|
||||
#endif
|
||||
session->server = ipInfo->dst;
|
||||
session->client = ipInfo->src;
|
||||
session->srvPort = (word16)tcpInfo->dstPort;
|
||||
|
30
src/ssl.c
30
src/ssl.c
@ -1749,6 +1749,35 @@ WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
#ifndef NO_WOLFSSL_CLIENT
|
||||
|
||||
int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
ctx->haveEMS = 0;
|
||||
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl)
|
||||
{
|
||||
if (ssl == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
ssl->options.haveEMS = 0;
|
||||
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WOLFSSL_LEANPSK
|
||||
|
||||
int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags)
|
||||
@ -7847,6 +7876,7 @@ int AddSession(WOLFSSL* ssl)
|
||||
|
||||
XMEMCPY(SessionCache[row].Sessions[idx].masterSecret,
|
||||
ssl->arrays->masterSecret, SECRET_LEN);
|
||||
SessionCache[row].Sessions[idx].haveEMS = ssl->options.haveEMS;
|
||||
XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays->sessionID,
|
||||
ID_LEN);
|
||||
SessionCache[row].Sessions[idx].sessionIDSz = ssl->arrays->sessionIDSz;
|
||||
|
133
src/tls.c
133
src/tls.c
@ -341,21 +341,23 @@ static int PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
|
||||
#endif
|
||||
|
||||
|
||||
int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
|
||||
int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen)
|
||||
{
|
||||
const byte* side;
|
||||
byte handshake_hash[HSHASH_SZ];
|
||||
word32 hashSz = FINISHED_SZ;
|
||||
word32 hashSz = FINISHED_SZ;
|
||||
|
||||
if (ssl == NULL || hash == NULL || hashLen == NULL || *hashLen < HSHASH_SZ)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifndef NO_OLD_TLS
|
||||
wc_Md5GetHash(&ssl->hsHashes->hashMd5, handshake_hash);
|
||||
wc_ShaGetHash(&ssl->hsHashes->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
|
||||
wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash);
|
||||
wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[MD5_DIGEST_SIZE]);
|
||||
#endif
|
||||
|
||||
if (IsAtLeastTLSv1_2(ssl)) {
|
||||
#ifndef NO_SHA256
|
||||
if (ssl->specs.mac_algorithm <= sha256_mac || ssl->specs.mac_algorithm == blake2b_mac) {
|
||||
int ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256,handshake_hash);
|
||||
if (ssl->specs.mac_algorithm <= sha256_mac ||
|
||||
ssl->specs.mac_algorithm == blake2b_mac) {
|
||||
int ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
@ -365,7 +367,7 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
if (ssl->specs.mac_algorithm == sha384_mac) {
|
||||
int ret = wc_Sha384Final(&ssl->hsHashes->hashSha384,handshake_hash);
|
||||
int ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
@ -375,6 +377,23 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
|
||||
#endif
|
||||
}
|
||||
|
||||
*hashLen = hashSz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
|
||||
{
|
||||
int ret;
|
||||
const byte* side;
|
||||
byte handshake_hash[HSHASH_SZ];
|
||||
word32 hashSz = HSHASH_SZ;
|
||||
|
||||
ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
|
||||
side = tls_client;
|
||||
else
|
||||
@ -420,6 +439,10 @@ ProtocolVersion MakeTLSv1_2(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] =
|
||||
"extended master secret";
|
||||
#endif
|
||||
static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
|
||||
static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion";
|
||||
|
||||
@ -490,10 +513,41 @@ int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen,
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
|
||||
/* External facing wrapper so user can call as well, 0 on success */
|
||||
int wolfSSL_MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
|
||||
const byte* pms, word32 pmsLen,
|
||||
const byte* sHash, word32 sHashLen,
|
||||
int tls1_2, int hash_type)
|
||||
{
|
||||
return PRF(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ,
|
||||
sHash, sHashLen, tls1_2, hash_type);
|
||||
}
|
||||
|
||||
#endif /* HAVE_EXTENDED_MASTER */
|
||||
|
||||
|
||||
int MakeTlsMasterSecret(WOLFSSL* ssl)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
byte handshake_hash[HSHASH_SZ];
|
||||
word32 hashSz = HSHASH_SZ;
|
||||
|
||||
if (ssl->options.haveEMS) {
|
||||
|
||||
ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wolfSSL_MakeTlsExtendedMasterSecret(
|
||||
ssl->arrays->masterSecret, SECRET_LEN,
|
||||
ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
|
||||
handshake_hash, hashSz,
|
||||
IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm);
|
||||
} else
|
||||
#endif
|
||||
ret = wolfSSL_MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN,
|
||||
ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
|
||||
ssl->arrays->clientRandom, ssl->arrays->serverRandom,
|
||||
@ -4434,7 +4488,13 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl)
|
||||
length += TLSX_GetSize(ssl->ctx->extensions, semaphore, 1);
|
||||
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
|
||||
length += ssl->suites->hashSigAlgoSz + HELLO_EXT_LEN;
|
||||
length += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ
|
||||
+ ssl->suites->hashSigAlgoSz;
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (ssl->options.haveEMS)
|
||||
length += HELLO_EXT_SZ;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (length)
|
||||
@ -4465,15 +4525,15 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output)
|
||||
offset += TLSX_Write(ssl->ctx->extensions, output + offset,
|
||||
semaphore, 1);
|
||||
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
|
||||
{
|
||||
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) {
|
||||
int i;
|
||||
/* extension type */
|
||||
c16toa(HELLO_EXT_SIG_ALGO, output + offset);
|
||||
offset += HELLO_EXT_TYPE_SZ;
|
||||
|
||||
/* extension data length */
|
||||
c16toa(OPAQUE16_LEN + ssl->suites->hashSigAlgoSz, output + offset);
|
||||
c16toa(OPAQUE16_LEN + ssl->suites->hashSigAlgoSz,
|
||||
output + offset);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
/* sig algos length */
|
||||
@ -4485,6 +4545,15 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output)
|
||||
output[offset] = ssl->suites->hashSigAlgo[i];
|
||||
}
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (ssl->options.haveEMS) {
|
||||
c16toa(HELLO_EXT_EXTMS, output + offset);
|
||||
offset += HELLO_EXT_TYPE_SZ;
|
||||
c16toa(0, output + offset);
|
||||
offset += HELLO_EXT_SZ_SZ;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (offset > OPAQUE16_LEN)
|
||||
c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
|
||||
}
|
||||
@ -4511,13 +4580,18 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (ssl->options.haveEMS)
|
||||
length += HELLO_EXT_SZ;
|
||||
#endif
|
||||
|
||||
if (TLSX_SupportExtensions(ssl))
|
||||
length += TLSX_GetSize(ssl->extensions, semaphore, 0);
|
||||
|
||||
/* All the response data is set at the ssl object only, so no ctx here. */
|
||||
|
||||
if (length)
|
||||
length += OPAQUE16_LEN; /* for total length storage */
|
||||
length += OPAQUE16_LEN; /* for total length storage. */
|
||||
|
||||
return length;
|
||||
}
|
||||
@ -4534,6 +4608,15 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output)
|
||||
|
||||
offset += TLSX_Write(ssl->extensions, output + offset, semaphore, 0);
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (ssl->options.haveEMS) {
|
||||
c16toa(HELLO_EXT_EXTMS, output + offset);
|
||||
offset += HELLO_EXT_TYPE_SZ;
|
||||
c16toa(0, output + offset);
|
||||
offset += HELLO_EXT_SZ_SZ;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (offset > OPAQUE16_LEN)
|
||||
c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
|
||||
}
|
||||
@ -4549,6 +4632,9 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest,
|
||||
{
|
||||
int ret = 0;
|
||||
word16 offset = 0;
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
byte pendingEMS = 0;
|
||||
#endif
|
||||
|
||||
if (!ssl || !input || (isRequest && !suites))
|
||||
return BAD_FUNC_ARG;
|
||||
@ -4606,6 +4692,18 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest,
|
||||
ret = CSR2_PARSE(ssl, input + offset, size, isRequest);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
case HELLO_EXT_EXTMS:
|
||||
WOLFSSL_MSG("Extended Master Secret extension received");
|
||||
|
||||
#ifndef NO_WOLFSSL_SERVER
|
||||
if (isRequest)
|
||||
ssl->options.haveEMS = 1;
|
||||
#endif
|
||||
pendingEMS = 1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TLSX_RENEGOTIATION_INFO:
|
||||
WOLFSSL_MSG("Secure Renegotiation extension received");
|
||||
|
||||
@ -4655,6 +4753,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest,
|
||||
offset += size;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (!isRequest && ssl->options.haveEMS && !pendingEMS)
|
||||
ssl->options.haveEMS = 0;
|
||||
#endif
|
||||
|
||||
if (ret == 0)
|
||||
ret = SNI_VERIFY_PARSE(ssl, isRequest);
|
||||
|
||||
|
23
tests/api.c
23
tests/api.c
@ -1927,6 +1927,28 @@ static void test_wolfSSL_UseALPN(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_wolfSSL_DisableExtendedMasterSecret(void)
|
||||
{
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
|
||||
WOLFSSL *ssl = wolfSSL_new(ctx);
|
||||
|
||||
AssertNotNull(ctx);
|
||||
AssertNotNull(ssl);
|
||||
|
||||
/* error cases */
|
||||
AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_DisableExtendedMasterSecret(NULL));
|
||||
AssertIntNE(SSL_SUCCESS, wolfSSL_DisableExtendedMasterSecret(NULL));
|
||||
|
||||
/* success cases */
|
||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_DisableExtendedMasterSecret(ctx));
|
||||
AssertIntEQ(SSL_SUCCESS, wolfSSL_DisableExtendedMasterSecret(ssl));
|
||||
|
||||
wolfSSL_free(ssl);
|
||||
wolfSSL_CTX_free(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
| X509 Tests
|
||||
*----------------------------------------------------------------------------*/
|
||||
@ -2129,6 +2151,7 @@ void ApiTest(void)
|
||||
test_wolfSSL_UseTruncatedHMAC();
|
||||
test_wolfSSL_UseSupportedCurve();
|
||||
test_wolfSSL_UseALPN();
|
||||
test_wolfSSL_DisableExtendedMasterSecret();
|
||||
|
||||
/* X509 tests */
|
||||
test_wolfSSL_X509_NAME_get_entry();
|
||||
|
@ -48,6 +48,7 @@
|
||||
static WOLFSSL_CTX* cipherSuiteCtx = NULL;
|
||||
static char nonblockFlag[] = "-N";
|
||||
static char noVerifyFlag[] = "-d";
|
||||
static char disableEMSFlag[] = "-n";
|
||||
static char flagSep[] = " ";
|
||||
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS)
|
||||
static char portFlag[] = "-p";
|
||||
@ -153,7 +154,8 @@ static int IsValidCipherSuite(const char* line, char* suite)
|
||||
|
||||
static int execute_test_case(int svr_argc, char** svr_argv,
|
||||
int cli_argc, char** cli_argv,
|
||||
int addNoVerify, int addNonBlocking)
|
||||
int addNoVerify, int addNonBlocking,
|
||||
int addDisableEMS)
|
||||
{
|
||||
#ifdef WOLFSSL_TIRTOS
|
||||
func_args cliArgs = {0};
|
||||
@ -270,6 +272,18 @@ static int execute_test_case(int svr_argc, char** svr_argv,
|
||||
cliArgs.argc = cli_argc;
|
||||
}
|
||||
}
|
||||
if (addDisableEMS) {
|
||||
printf("repeating test without extended master secret\n");
|
||||
added += 4; /* -n plus terminator */
|
||||
if (added >= MAX_COMMAND_SZ)
|
||||
printf("client command line too long\n");
|
||||
else {
|
||||
cli_argv[cli_argc++] = disableEMSFlag;
|
||||
strcat(commandLine, disableEMSFlag);
|
||||
strcat(commandLine, flagSep);
|
||||
cliArgs.argc = cli_argc;
|
||||
}
|
||||
}
|
||||
printf("trying client command line[%d]: %s\n", tests++, commandLine);
|
||||
|
||||
InitTcpReady(&ready);
|
||||
@ -437,12 +451,26 @@ static void test_harness(void* vargs)
|
||||
}
|
||||
|
||||
if (do_it) {
|
||||
ret = execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs,0,0);
|
||||
ret = execute_test_case(svrArgsSz, svrArgs,
|
||||
cliArgsSz, cliArgs, 0, 0, 0);
|
||||
/* don't repeat if not supported in build */
|
||||
if (ret == 0) {
|
||||
execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 0, 1);
|
||||
execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 1, 0);
|
||||
execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 1, 1);
|
||||
execute_test_case(svrArgsSz, svrArgs,
|
||||
cliArgsSz, cliArgs, 0, 1, 0);
|
||||
execute_test_case(svrArgsSz, svrArgs,
|
||||
cliArgsSz, cliArgs, 1, 0, 0);
|
||||
execute_test_case(svrArgsSz, svrArgs,
|
||||
cliArgsSz, cliArgs, 1, 1, 0);
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
execute_test_case(svrArgsSz, svrArgs,
|
||||
cliArgsSz, cliArgs, 0, 0, 1);
|
||||
execute_test_case(svrArgsSz, svrArgs,
|
||||
cliArgsSz, cliArgs, 0, 1, 1);
|
||||
execute_test_case(svrArgsSz, svrArgs,
|
||||
cliArgsSz, cliArgs, 1, 0, 1);
|
||||
execute_test_case(svrArgsSz, svrArgs,
|
||||
cliArgsSz, cliArgs, 1, 1, 1);
|
||||
#endif
|
||||
}
|
||||
svrArgsSz = 1;
|
||||
cliArgsSz = 1;
|
||||
|
@ -324,6 +324,21 @@ int wc_Sha256Hash(const byte* data, word32 len, byte* hash)
|
||||
#endif /* !defined(WOLFSSL_TI_HASH) */
|
||||
|
||||
#if defined(WOLFSSL_SHA512)
|
||||
int wc_Sha512GetHash(Sha512* sha512, byte* hash)
|
||||
{
|
||||
int ret;
|
||||
Sha512 save;
|
||||
|
||||
if (sha512 == NULL || hash == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
save= *sha512;
|
||||
ret = wc_Sha512Final(sha512, hash);
|
||||
*sha512 = save;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wc_Sha512Hash(const byte* data, word32 len, byte* hash)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -357,6 +372,21 @@ int wc_Sha512Hash(const byte* data, word32 len, byte* hash)
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_SHA384)
|
||||
int wc_Sha384GetHash(Sha384* sha384, byte* hash)
|
||||
{
|
||||
int ret;
|
||||
Sha384 save;
|
||||
|
||||
if (sha384 == NULL || hash == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
save= *sha384;
|
||||
ret = wc_Sha384Final(sha384, hash);
|
||||
*sha384 = save;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wc_Sha384Hash(const byte* data, word32 len, byte* hash)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -149,6 +149,7 @@ enum wolfSSL_ErrorCodes {
|
||||
DTLS_EXPORT_VER_E = -411, /* export version error */
|
||||
INPUT_SIZE_E = -412, /* input size too big error */
|
||||
CTX_INIT_MUTEX_E = -413, /* initialize ctx mutex error */
|
||||
EXT_MASTER_SECRET_NEEDED_E = -414, /* need EMS enabled to resume */
|
||||
/* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
|
||||
|
||||
/* begin negotiation parameter errors */
|
||||
|
@ -878,6 +878,7 @@ enum Misc {
|
||||
NO_COMPRESSION = 0,
|
||||
ZLIB_COMPRESSION = 221, /* wolfSSL zlib compression */
|
||||
HELLO_EXT_SIG_ALGO = 13, /* ID for the sig_algo hello extension */
|
||||
HELLO_EXT_EXTMS = 0x0017, /* ID for the extended master secret ext */
|
||||
SECRET_LEN = 48, /* pre RSA and all master */
|
||||
#if defined(WOLFSSL_MYSQL_COMPATIBLE)
|
||||
ENCRYPT_LEN = 1024, /* allow larger static buffer with mysql */
|
||||
@ -939,10 +940,10 @@ enum Misc {
|
||||
REQ_HEADER_SZ = 2, /* cert request header sz */
|
||||
HINT_LEN_SZ = 2, /* length of hint size field */
|
||||
TRUNCATED_HMAC_SZ = 10, /* length of hmac w/ truncated hmac extension */
|
||||
HELLO_EXT_SZ = 4, /* base length of a hello extension */
|
||||
HELLO_EXT_TYPE_SZ = 2, /* length of a hello extension type */
|
||||
HELLO_EXT_SZ = 8, /* total length of the lazy hello extensions */
|
||||
HELLO_EXT_LEN = 6, /* length of the lazy hello extensions */
|
||||
HELLO_EXT_SIGALGO_SZ = 2, /* length of signature algo extension */
|
||||
HELLO_EXT_SZ_SZ = 2, /* length of a hello extension size */
|
||||
HELLO_EXT_SIGALGO_SZ = 2, /* length of number of items in sigalgo list */
|
||||
HELLO_EXT_SIGALGO_MAX = 32, /* number of items in the signature algo list */
|
||||
|
||||
DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */
|
||||
@ -963,6 +964,7 @@ enum Misc {
|
||||
MAX_EXPORT_BUFFER = 500, /* max size of buffer for exporting */
|
||||
FINISHED_LABEL_SZ = 15, /* TLS finished label size */
|
||||
TLS_FINISHED_SZ = 12, /* TLS has a shorter size */
|
||||
EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */
|
||||
MASTER_LABEL_SZ = 13, /* TLS master secret label sz */
|
||||
KEY_LABEL_SZ = 13, /* TLS key block expansion sz */
|
||||
MAX_PRF_HALF = 256, /* Maximum half secret len */
|
||||
@ -1936,6 +1938,7 @@ struct WOLFSSL_CTX {
|
||||
byte quietShutdown; /* don't send close notify */
|
||||
byte groupMessages; /* group handshake messages before sending */
|
||||
byte minDowngrade; /* minimum downgrade version */
|
||||
byte haveEMS; /* have extended master secret extension */
|
||||
#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
|
||||
byte dtlsSctp; /* DTLS-over-SCTP mode */
|
||||
word16 dtlsMtuSz; /* DTLS MTU size */
|
||||
@ -2225,6 +2228,7 @@ struct WOLFSSL_SESSION {
|
||||
byte sessionID[ID_LEN]; /* id for protocol */
|
||||
byte sessionIDSz;
|
||||
byte masterSecret[SECRET_LEN]; /* stored secret */
|
||||
word16 haveEMS; /* ext master secret flag */
|
||||
#ifdef SESSION_CERTS
|
||||
WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */
|
||||
ProtocolVersion version; /* which version was used */
|
||||
@ -2409,6 +2413,7 @@ typedef struct Options {
|
||||
word16 dtlsSctp:1; /* DTLS-over-SCTP mode */
|
||||
#endif
|
||||
#endif
|
||||
word16 haveEMS:1; /* using extended master secret */
|
||||
|
||||
/* need full byte values for this section */
|
||||
byte processReply; /* nonblocking resume */
|
||||
@ -3028,6 +3033,8 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl);
|
||||
WOLFSSL_LOCAL Signer* GetCAByName(void* cm, byte* hash);
|
||||
#endif
|
||||
#endif /* !NO_CERTS */
|
||||
WOLFSSL_LOCAL int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash,
|
||||
word32* hashLen);
|
||||
WOLFSSL_LOCAL int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes,
|
||||
const byte* sender);
|
||||
WOLFSSL_LOCAL void FreeArrays(WOLFSSL* ssl, int keep);
|
||||
|
@ -117,6 +117,7 @@
|
||||
#define CLEAR_ACK_FAULT 80
|
||||
|
||||
#define BAD_DECRYPT_SIZE 81
|
||||
#define EXTENDED_MASTER_HASH_STR 82
|
||||
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */
|
||||
|
||||
|
||||
|
@ -98,5 +98,6 @@ STRINGTABLE
|
||||
80, "Clear ACK Fault"
|
||||
|
||||
81, "Bad Decrypt Size"
|
||||
82, "Extended Master Secret Hash Error"
|
||||
}
|
||||
|
||||
|
@ -1704,6 +1704,11 @@ WOLFSSL_API int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, unsigned short name);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* TLS Extended Master Secret Extension */
|
||||
WOLFSSL_API int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl);
|
||||
WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx);
|
||||
|
||||
|
||||
#define WOLFSSL_CRL_MONITOR 0x01 /* monitor this dir flag */
|
||||
#define WOLFSSL_CRL_START_MON 0x02 /* start monitoring flag */
|
||||
|
||||
@ -1725,6 +1730,12 @@ int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, unsigned int msLen,
|
||||
const unsigned char* cr, const unsigned char* sr,
|
||||
int tls1_2, int hash_type);
|
||||
|
||||
WOLFSSL_API
|
||||
int wolfSSL_MakeTlsExtendedMasterSecret(unsigned char* ms, unsigned int msLen,
|
||||
const unsigned char* pms, unsigned int pmsLen,
|
||||
const unsigned char* sHash, unsigned int sHashLen,
|
||||
int tls1_2, int hash_type);
|
||||
|
||||
WOLFSSL_API
|
||||
int wolfSSL_DeriveTlsKeys(unsigned char* key_data, unsigned int keyLen,
|
||||
const unsigned char* ms, unsigned int msLen,
|
||||
|
@ -105,10 +105,12 @@ WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*);
|
||||
|
||||
#ifdef WOLFSSL_SHA512
|
||||
#include <wolfssl/wolfcrypt/sha512.h>
|
||||
WOLFSSL_API int wc_Sha512GetHash(Sha512*, byte*);
|
||||
WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*);
|
||||
#define wc_Sha512Free(d)
|
||||
|
||||
#if defined(WOLFSSL_SHA384)
|
||||
WOLFSSL_API int wc_Sha384GetHash(Sha384*, byte*);
|
||||
WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*);
|
||||
#define wc_Sha384Free(d)
|
||||
#endif /* defined(WOLFSSL_SHA384) */
|
||||
|
Reference in New Issue
Block a user