Merge pull request #545 from ejohnstown/ems

Extended Master Secret
This commit is contained in:
toddouska
2016-09-15 11:25:41 -07:00
committed by GitHub
17 changed files with 789 additions and 100 deletions

View File

@ -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 */

View File

@ -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"

View File

@ -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) {

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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
View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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 !!!! */

View File

@ -98,5 +98,6 @@ STRINGTABLE
80, "Clear ACK Fault"
81, "Bad Decrypt Size"
82, "Extended Master Secret Hash Error"
}

View File

@ -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,

View File

@ -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) */