Merge pull request #995 from SparkiDev/tls13_cookie

Add TLS v1.3 Cookie extension support
This commit is contained in:
toddouska
2017-06-28 10:12:49 -07:00
committed by GitHub
9 changed files with 784 additions and 147 deletions

View File

@ -297,6 +297,22 @@ then
fi
# Post-handshake Authentication
AC_ARG_ENABLE([hrrcookie],
[AS_HELP_STRING([--enable-hrrcookie],[Enable the server to send Cookie Extension in HRR with state (default: disabled)])],
[ ENABLED_SEND_HRR_COOKIE=$enableval ],
[ ENABLED_SEND_HRR_COOKIE=no ]
)
if test "$ENABLED_SEND_HRR_COOKIE" = "yes"
then
if test "x$ENABLED_TLS13" = "xno"
then
AC_MSG_ERROR([cannot enable hrrcookie without enabling tls13.])
fi
AM_CFLAGS="-DWOLFSSL_SEND_HRR_COOKIE $AM_CFLAGS"
fi
AC_ARG_ENABLE([rng],
[AS_HELP_STRING([--enable-rng],[Enable compiling and using RNG (default: enabled)])],
[ ENABLED_RNG=$enableval ],
@ -3798,6 +3814,7 @@ echo " * TLS v1.3: $ENABLED_TLS13"
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 " * Send State in HRR Cookie: $ENABLED_SEND_HRR_COOKIE"
echo " * OCSP: $ENABLED_OCSP"
echo " * OCSP Stapling: $ENABLED_CERTIFICATE_STATUS_REQUEST"
echo " * OCSP Stapling v2: $ENABLED_CERTIFICATE_STATUS_REQUEST_V2"

View File

@ -379,6 +379,9 @@ static void Usage(void)
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
printf("-Q Request certificate from client post-handshake\n");
#endif
#ifdef WOLFSSL_SEND_HRR_COOKIE
printf("-J Server sends Cookie Extension containing state\n");
#endif
#endif
#ifdef WOLFSSL_EARLY_DATA
printf("-0 Early data read from client (0-RTT handshake)\n");
@ -474,6 +477,9 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#ifdef WOLFSSL_EARLY_DATA
int earlyData = 0;
#endif
#ifdef WOLFSSL_SEND_HRR_COOKIE
int hrrCookie = 0;
#endif
#ifdef WOLFSSL_STATIC_MEMORY
#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \
@ -518,10 +524,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#ifdef WOLFSSL_VXWORKS
useAnyAddr = 1;
#else
/* Not Used: h, m, t, y, z, F, J, M, T, V, W, X, Y */
/* Not Used: h, m, t, y, z, F, M, T, V, W, X, Y */
while ((ch = mygetopt(argc, argv, "?"
"abc:defgijk:l:nop:q:rsuv:wx"
"A:B:C:D:E:GHIKL:NO:PQR:S:UYZ:""0")) != -1) {
"A:B:C:D:E:GHIJKL:NO:PQR:S:UYZ:"
"0")) != -1) {
switch (ch) {
case '?' :
Usage();
@ -746,6 +753,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#endif
break;
case 'J' :
#ifdef WOLFSSL_SEND_HRR_COOKIE
hrrCookie = 1;
#endif
break;
case '0' :
#ifdef WOLFSSL_EARLY_DATA
earlyData = 1;
@ -1083,6 +1096,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
wolfSSL_KeepArrays(ssl);
#endif
#ifdef WOLFSSL_SEND_HRR_COOKIE
if (hrrCookie && wolfSSL_send_hrr_cookie(ssl, NULL, 0) != SSL_SUCCESS) {
err_sys("unable to set use of cookie with HRR msg");
}
#endif
#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL)
{
WOLFSSL_MEM_STATS mem_stats;

View File

@ -95,6 +95,22 @@ if [ $RESULT -ne 0 ]; then
fi
echo ""
# Use HelloRetryRequest with TLS v1.3 server / TLS v1.3 client using cookie
echo -e "\n\nTLS v1.3 HelloRetryRequest with cookie"
port=0
./examples/server/server -v 4 -J -R $ready_file -p $port &
server_pid=$!
create_port
./examples/client/client -v 4 -J -p $port
RESULT=$?
remove_ready_file
if [ $RESULT -ne 0 ]; then
echo -e "\n\nTLS v1.3 HelloRetryRequest with cookie not working"
do_cleanup
exit 1
fi
echo ""
# Use HelloRetryRequest with TLS v1.3 server / TLS v1.3 client - SHA384.
echo -e "\n\nTLS v1.3 HelloRetryRequest - SHA384"
port=0

View File

@ -4550,6 +4550,10 @@ void SSL_ResourceFree(WOLFSSL* ssl)
ShrinkInputBuffer(ssl, FORCED_FREE);
if (ssl->buffers.outputBuffer.dynamicFlag)
ShrinkOutputBuffer(ssl);
#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap,
DYNAMIC_TYPE_COOKIE_PWD);
#endif
#ifdef WOLFSSL_DTLS
DtlsMsgPoolReset(ssl);
if (ssl->dtls_rx_msg_list != NULL) {
@ -13934,6 +13938,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case POST_HAND_AUTH_ERROR:
return "Client will not do post handshake authentication";
case HRR_COOKIE_ERROR:
return "Cookie does not match one sent in HelloRetryRequest";
default :
return "unknown error number";
}
@ -15742,7 +15749,7 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
if (QSH_Init(ssl) != 0)
return MEMORY_E;
#endif
extSz = TLSX_GetRequestSize(ssl);
extSz = TLSX_GetRequestSize(ssl, client_hello);
if (extSz != 0)
length += extSz;
#else
@ -15835,7 +15842,7 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo,
output[idx++] = NO_COMPRESSION;
#ifdef HAVE_TLS_EXTENSIONS
idx += TLSX_WriteRequest(ssl, output + idx);
idx += TLSX_WriteRequest(ssl, output + idx, client_hello);
(void)idx; /* suppress analyzer warning, keep idx current */
#else

404
src/tls.c
View File

@ -4452,6 +4452,170 @@ static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data,
#endif /* WOLFSSL_TLS13 */
#if defined(WOLFSSL_TLS13)
/******************************************************************************/
/* Cookie */
/******************************************************************************/
/* Free the cookie data.
*
* cookie Cookie data.
* heap The heap used for allocation.
*/
static void TLSX_Cookie_FreeAll(Cookie* cookie, void* heap)
{
(void)heap;
if (cookie != NULL)
XFREE(cookie, heap, DYNAMIC_TYPE_TLSX);
}
/* Get the size of the encoded Cookie extension.
* In messages: ClientHello and HelloRetryRequest.
*
* cookie The cookie to write.
* msgType The type of the message this extension is being written into.
* returns the number of bytes of the encoded Cookie extension.
*/
static word16 TLSX_Cookie_GetSize(Cookie* cookie, byte msgType)
{
if (msgType == client_hello || msgType == hello_retry_request)
return OPAQUE16_LEN + cookie->len;
return SANITY_MSG_E;
}
/* Writes the Cookie extension into the output buffer.
* Assumes that the the output buffer is big enough to hold data.
* In messages: ClientHello and HelloRetryRequest.
*
* cookie The cookie to write.
* output The buffer to write into.
* msgType The type of the message this extension is being written into.
* returns the number of bytes written into the buffer.
*/
static word16 TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType)
{
if (msgType == client_hello || msgType == hello_retry_request) {
c16toa(cookie->len, output);
output += OPAQUE16_LEN;
XMEMCPY(output, &cookie->data, cookie->len);
return OPAQUE16_LEN + cookie->len;
}
return SANITY_MSG_E;
}
/* Parse the Cookie extension.
* In messages: ClientHello and HelloRetryRequest.
*
* ssl The SSL/TLS object.
* input The extension data.
* length The length of the extension data.
* msgType The type of the message this extension is being parsed from.
* returns 0 on success and other values indicate failure.
*/
static int TLSX_Cookie_Parse(WOLFSSL* ssl, byte* input, word16 length,
byte msgType)
{
word16 len;
word16 idx = 0;
TLSX* extension;
Cookie* cookie;
if (msgType != client_hello && msgType != hello_retry_request)
return SANITY_MSG_E;
/* Message contains length and Cookie which must be at least one byte
* in length.
*/
if (length < OPAQUE16_LEN + 1)
return BUFFER_E;
ato16(input + idx, &len);
idx += OPAQUE16_LEN;
if (length - idx != len)
return BUFFER_E;
if (msgType == hello_retry_request)
return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0);
/* client_hello */
extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
if (extension == NULL)
return HRR_COOKIE_ERROR;
cookie = (Cookie*)extension->data;
if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0)
return HRR_COOKIE_ERROR;
/* Request seen. */
extension->resp = 0;
return 0;
}
/* Use the data to create a new Cookie object in the extensions.
*
* ssl SSL/TLS object.
* data Cookie data.
* len Length of cookie data in bytes.
* mac MAC data.
* macSz Length of MAC data in bytes.
* resp Indicates the extension will go into a response (HelloRetryRequest).
* returns 0 on success and other values indicate failure.
*/
int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, byte* mac,
byte macSz, int resp)
{
int ret = 0;
TLSX* extension;
Cookie* cookie;
/* Find the cookie extension if it exists. */
extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
if (extension == NULL) {
/* Push new cookie extension. */
ret = TLSX_Push(&ssl->extensions, TLSX_COOKIE, NULL, ssl->heap);
if (ret != 0)
return ret;
extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
if (extension == NULL)
return MEMORY_E;
}
/* The Cookie structure has one byte for cookie data already. */
cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz - 1, ssl->heap,
DYNAMIC_TYPE_TLSX);
if (cookie == NULL)
return MEMORY_E;
cookie->len = len + macSz;
XMEMCPY(&cookie->data, data, len);
if (mac != NULL)
XMEMCPY(&cookie->data + len, mac, macSz);
extension->data = (void*)cookie;
extension->resp = resp;
return 0;
}
#define CKE_FREE_ALL TLSX_Cookie_FreeAll
#define CKE_GET_SIZE TLSX_Cookie_GetSize
#define CKE_WRITE TLSX_Cookie_Write
#define CKE_PARSE TLSX_Cookie_Parse
#else
#define CKE_FREE_ALL(a, b) 0
#define CKE_GET_SIZE(a, b) 0
#define CKE_WRITE(a, b, c) 0
#define CKE_PARSE(a, b, c, d) 0
#endif
/******************************************************************************/
/* Sugnature Algorithms */
/******************************************************************************/
@ -6376,7 +6540,8 @@ int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes)
* Only in ClientHello.
*
* msgType The type of the message this extension is being written into.
* returns the number of bytes of the encoded key share extension.
* returns the number of bytes of the encoded Post-Hanshake Authentication
* extension.
*/
static word16 TLSX_PostHandAuth_GetSize(byte msgType)
{
@ -6478,7 +6643,7 @@ static int TLSX_PostHandAuth_Use(WOLFSSL* ssl)
* In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
*
* msgType The type of the message this extension is being written into.
* returns the number of bytes of the encoded key share extension.
* returns the number of bytes of the encoded Early Data Indication extension.
*/
static word16 TLSX_EarlyData_GetSize(byte msgType)
{
@ -6561,10 +6726,10 @@ int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max)
int ret = 0;
TLSX* extension;
/* Find the early extension if it exists. */
/* Find the early data extension if it exists. */
extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
if (extension == NULL) {
/* Push new early extension. */
/* Push new early data extension. */
ret = TLSX_Push(&ssl->extensions, TLSX_EARLY_DATA, NULL, ssl->heap);
if (ret != 0)
return ret;
@ -6665,6 +6830,10 @@ void TLSX_FreeAll(TLSX* list, void* heap)
case TLSX_SUPPORTED_VERSIONS:
break;
case TLSX_COOKIE:
CKE_FREE_ALL((Cookie*)extension->data, heap);
break;
case TLSX_KEY_SHARE:
KS_FREE_ALL((KeyShareEntry*)extension->data, heap);
break;
@ -6782,6 +6951,10 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType)
length += SV_GET_SIZE(extension->data);
break;
case TLSX_COOKIE:
length += CKE_GET_SIZE((Cookie*)extension->data, msgType);
break;
case TLSX_KEY_SHARE:
length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType);
break;
@ -6919,6 +7092,12 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
offset += SV_WRITE(extension->data, output + offset);
break;
case TLSX_COOKIE:
WOLFSSL_MSG("Cookie extension to write");
offset += CKE_WRITE((Cookie*)extension->data, output + offset,
msgType);
break;
case TLSX_KEY_SHARE:
WOLFSSL_MSG("Key Share extension to write");
offset += KS_WRITE((KeyShareEntry*)extension->data,
@ -7531,13 +7710,14 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
#ifndef NO_WOLFSSL_CLIENT
/** Tells the buffered size of extensions to be sent into the client hello. */
word16 TLSX_GetRequestSize(WOLFSSL* ssl)
word16 TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType)
{
word16 length = 0;
byte semaphore[SEMAPHORE_SIZE] = {0};
if (TLSX_SupportExtensions(ssl)) {
byte semaphore[SEMAPHORE_SIZE] = {0};
if (!TLSX_SupportExtensions(ssl))
return 0;
if (msgType == client_hello) {
EC_VALIDATE_REQUEST(ssl, semaphore);
QSH_VALIDATE_REQUEST(ssl, semaphore);
WOLF_STK_VALIDATE_REQUEST(ssl);
@ -7547,28 +7727,43 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl)
if (!IsAtLeastTLSv1_2(ssl))
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
if (!IsAtLeastTLSv1_3(ssl->version)) {
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
#endif
#ifdef WOLFSSL_EARLY_DATA
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
#endif
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
#endif
}
#endif
if (ssl->extensions)
length += TLSX_GetSize(ssl->extensions, semaphore, client_hello);
if (ssl->ctx && ssl->ctx->extensions) {
length += TLSX_GetSize(ssl->ctx->extensions, semaphore,
client_hello);
}
#ifdef HAVE_EXTENDED_MASTER
if (ssl->options.haveEMS)
length += HELLO_EXT_SZ;
#endif
}
#ifdef WOLFSSL_TLS13
#ifndef NO_CERTS
else if (msgType == certificate_request) {
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
/* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
* TLSX_CERTIFICATE_AUTHORITIES, OID_FILTERS
*/
}
#endif
#endif
if (ssl->extensions)
length += TLSX_GetSize(ssl->extensions, semaphore, msgType);
if (ssl->ctx && ssl->ctx->extensions)
length += TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType);
#ifdef HAVE_EXTENDED_MASTER
if (msgType == client_hello && ssl->options.haveEMS)
length += HELLO_EXT_SZ;
#endif
if (length)
length += OPAQUE16_LEN; /* for total length storage. */
@ -7577,65 +7772,91 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl)
}
/** Writes the extensions to be sent into the client hello. */
word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output)
word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType)
{
word16 offset = 0;
byte semaphore[SEMAPHORE_SIZE] = {0};
if (TLSX_SupportExtensions(ssl) && output) {
byte semaphore[SEMAPHORE_SIZE] = {0};
if (!TLSX_SupportExtensions(ssl) || output == NULL)
return 0;
offset += OPAQUE16_LEN; /* extensions length */
offset += OPAQUE16_LEN; /* extensions length */
if (msgType == client_hello) {
EC_VALIDATE_REQUEST(ssl, semaphore);
WOLF_STK_VALIDATE_REQUEST(ssl);
QSH_VALIDATE_REQUEST(ssl, semaphore);
if (ssl->suites->hashSigAlgoSz == 0)
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
#if defined(WOLFSSL_TLS13)
#ifdef WOLFSSL_TLS13
if (!IsAtLeastTLSv1_2(ssl))
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
if (!IsAtLeastTLSv1_3(ssl->version)) {
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
#endif
#ifdef WOLFSSL_EARLY_DATA
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
#endif
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
#endif
}
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
/* Must write Pre-shared Key extension at the end in TLS v1.3.
* Must not write out Pre-shared Key extension in earlier versions of
* protocol.
*/
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
#endif
#endif
}
#ifdef WOLFSSL_TLS13
#ifndef NO_CERT
else if (msgType == certificate_request) {
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
/* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
* TLSX_CERTIFICATE_AUTHORITIES, TLSX_OID_FILTERS
*/
}
#endif
#endif
if (ssl->extensions)
offset += TLSX_Write(ssl->extensions, output + offset, semaphore,
client_hello);
if (ssl->ctx && ssl->ctx->extensions)
offset += TLSX_Write(ssl->ctx->extensions, output + offset,
semaphore, client_hello);
if (ssl->extensions) {
offset += TLSX_Write(ssl->extensions, output + offset, semaphore,
msgType);
}
if (ssl->ctx && ssl->ctx->extensions) {
offset += TLSX_Write(ssl->ctx->extensions, output + offset, semaphore,
msgType);
}
#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;
}
if (msgType == client_hello && ssl->options.haveEMS) {
c16toa(HELLO_EXT_EXTMS, output + offset);
offset += HELLO_EXT_TYPE_SZ;
c16toa(0, output + offset);
offset += HELLO_EXT_SZ_SZ;
}
#endif
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(ssl->version)) {
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
if (msgType == client_hello && IsAtLeastTLSv1_3(ssl->version)) {
/* Write out what we can of Pre-shared key extension. */
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
offset += TLSX_Write(ssl->extensions, output + offset, semaphore,
client_hello);
}
#endif
offset += TLSX_Write(ssl->extensions, output + offset, semaphore,
client_hello);
}
#endif
if (offset > OPAQUE16_LEN)
c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
}
if (offset > OPAQUE16_LEN || msgType != client_hello)
c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
return offset;
}
@ -7653,14 +7874,20 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType)
switch (msgType) {
case server_hello:
#ifdef WOLFSSL_TLS13
case hello_retry_request:
if (ssl->options.tls1_3) {
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
if (ssl->options.tls1_3) {
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
#endif
}
}
#endif
break;
#ifdef WOLFSSL_TLS13
case hello_retry_request:
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
#endif
break;
#ifdef WOLFSSL_TLS13
@ -7671,19 +7898,22 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType)
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
#endif
break;
#ifndef NO_CERTS
case certificate_request:
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
#ifdef WOLFSSL_EARLY_DATA
case session_ticket:
if (ssl->options.tls1_3) {
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
}
break;
#endif
#ifdef WOLFSSL_EARLY_DATA
case session_ticket:
if (ssl->options.tls1_3) {
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
}
break;
#ifndef NO_CERT
case certificate:
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
/* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
* TLSX_SERVER_CERTIFICATE_TYPE
*/
break;
#endif
#endif
}
@ -7707,7 +7937,7 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType)
/* All the response data is set at the ssl object only, so no ctx here. */
if (length || (msgType != server_hello))
if (length || msgType != server_hello)
length += OPAQUE16_LEN; /* for total length storage. */
return length;
@ -7724,7 +7954,6 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType)
switch (msgType) {
case server_hello:
#ifdef WOLFSSL_TLS13
case hello_retry_request:
if (ssl->options.tls1_3) {
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
@ -7734,6 +7963,12 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType)
}
#endif
break;
#ifdef WOLFSSL_TLS13
case hello_retry_request:
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
#endif
break;
#ifdef WOLFSSL_TLS13
case encrypted_extensions:
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET));
@ -7743,10 +7978,12 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType)
#endif
break;
#ifndef NO_CERTS
case certificate_request:
case certificate:
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore,
TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
/* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
* TLSX_SERVER_CERTIFICATE_TYPE
*/
break;
#endif
#ifdef WOLFSSL_EARLY_DATA
@ -7765,6 +8002,15 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType)
offset += TLSX_Write(ssl->extensions, output + offset, semaphore,
msgType);
#ifdef WOLFSSL_TLS13
if (msgType == hello_retry_request) {
XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
offset += TLSX_Write(ssl->extensions, output + offset, semaphore,
msgType);
}
#endif
#ifdef HAVE_EXTENDED_MASTER
if (ssl->options.haveEMS && msgType == server_hello) {
c16toa(HELLO_EXT_EXTMS, output + offset);
@ -7774,7 +8020,7 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType)
}
#endif
if (offset > OPAQUE16_LEN || msgType == encrypted_extensions)
if (offset > OPAQUE16_LEN || msgType != server_hello)
c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
}
@ -7977,6 +8223,20 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
ret = SV_PARSE(ssl, input + offset, size);
break;
case TLSX_COOKIE:
WOLFSSL_MSG("Cookie extension received");
if (!IsAtLeastTLSv1_3(ssl->version))
break;
if (IsAtLeastTLSv1_3(ssl->version) &&
msgType != client_hello &&
msgType != hello_retry_request) {
return EXT_NOT_ALLOWED;
}
ret = CKE_PARSE(ssl, input + offset, size, msgType);
break;
case TLSX_KEY_SHARE:
WOLFSSL_MSG("Key Share extension received");

View File

@ -1366,60 +1366,6 @@ static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz)
}
#endif
#ifndef WOLFSSL_TLS13_DRAFT_18
/* The offset into MessageHash of the low byte of the length field. */
#define MSG_HASH_LEN_OFFSET 3
/* Restart the Hanshake hash with a hash of the previous messages.
*
* ssl The SSL/TLS object.
* returns 0 on success, otherwise failure.
*/
static int RestartHandshakeHash(WOLFSSL* ssl)
{
int ret;
Hashes hashes;
byte header[] = { message_hash, 0, 0, 0 };
byte* hash = NULL;
ret = BuildCertHashes(ssl, &hashes);
if (ret != 0)
return ret;
ret = InitHandshakeHashes(ssl);
if (ret != 0)
return ret;
switch (ssl->specs.mac_algorithm) {
#ifndef NO_SHA256
case sha256_mac:
header[MSG_HASH_LEN_OFFSET] = SHA256_DIGEST_SIZE;
hash = hashes.sha256;
break;
#endif
#ifdef WOLFSSL_SHA384
case sha384_mac:
header[MSG_HASH_LEN_OFFSET] = SHA384_DIGEST_SIZE;
hash = hashes.sha384;
break;
#endif
#ifdef WOLFSSL_SHA512
case sha512_mac:
header[MSG_HASH_LEN_OFFSET] = SHA512_DIGEST_SIZE;
hash = hashes.sha512;
break;
#endif
}
WOLFSSL_MSG("Restart Hash");
WOLFSSL_BUFFER(hash, header[3]);
ret = HashOutputRaw(ssl, header, sizeof(header));
if (ret != 0)
return ret;
return HashOutputRaw(ssl, hash, header[MSG_HASH_LEN_OFFSET]);
}
#endif
/* Extract the handshake header information.
*
* ssl The SSL/TLS object.
@ -2348,7 +2294,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
return MEMORY_E;
#endif
/* Include length of TLS extensions. */
length += TLSX_GetRequestSize(ssl);
length += TLSX_GetRequestSize(ssl, client_hello);
/* Total message size. */
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
@ -2396,7 +2342,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
output[idx++] = NO_COMPRESSION;
/* Write out extensions for a request. */
idx += TLSX_WriteRequest(ssl, output + idx);
idx += TLSX_WriteRequest(ssl, output + idx, client_hello);
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
/* Resumption has a specific set of extensions and binder is calculated
@ -2429,6 +2375,117 @@ int SendTls13ClientHello(WOLFSSL* ssl)
return ret;
}
#ifndef WOLFSSL_TLS13_DRAFT_18
#ifdef WOLFSSL_SEND_HRR_COOKIE
/* Create Cookie extension using the hash of the first ClientHello.
*
* ssl SSL/TLS object.
* hash The hash data.
* hashSz The size of the hash data in bytes.
* returns 0 on success, otherwise failure.
*/
static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz)
{
int ret;
byte mac[MAX_DIGEST_SIZE];
Hmac cookieHmac;
byte cookieType;
byte macSz;
#if !defined(NO_SHA) && defined(NO_SHA256)
cookieType = SHA;
macSz = SHA_DIGEST_SIZE;
#endif /* NO_SHA */
#ifndef NO_SHA256
cookieType = SHA256;
macSz = SHA256_DIGEST_SIZE;
#endif /* NO_SHA256 */
ret = wc_HmacSetKey(&cookieHmac, cookieType,
ssl->buffers.tls13CookieSecret.buffer,
ssl->buffers.tls13CookieSecret.length);
if (ret != 0)
return ret;
if ((ret = wc_HmacUpdate(&cookieHmac, hash, hashSz)) != 0)
return ret;
if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
return ret;
/* The cookie data is the hash and the integrity check. */
return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1);
}
#endif
/* Restart the Hanshake hash with a hash of the previous messages.
*
* ssl The SSL/TLS object.
* returns 0 on success, otherwise failure.
*/
static int RestartHandshakeHash(WOLFSSL* ssl)
{
int ret;
Hashes hashes;
byte header[HANDSHAKE_HEADER_SZ];
byte* hash = NULL;
byte hashSz = 0;
ret = BuildCertHashes(ssl, &hashes);
if (ret != 0)
return ret;
switch (ssl->specs.mac_algorithm) {
#ifndef NO_SHA256
case sha256_mac:
hash = hashes.sha256;
break;
#endif
#ifdef WOLFSSL_SHA384
case sha384_mac:
hash = hashes.sha384;
break;
#endif
#ifdef WOLFSSL_SHA512
case sha512_mac:
hash = hashes.sha512;
break;
#endif
}
hashSz = ssl->specs.hash_size;
AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl);
WOLFSSL_MSG("Restart Hash");
WOLFSSL_BUFFER(hash, hashSz);
#ifdef WOLFSSL_SEND_HRR_COOKIE
if (ssl->options.sendCookie) {
byte cookie[OPAQUE8_LEN + MAX_DIGEST_SIZE + OPAQUE16_LEN * 2];
TLSX* ext;
word32 idx = 0;
/* Cookie Data = Hash Len | Hash | CS | KeyShare Group */
cookie[idx++] = hashSz;
XMEMCPY(cookie + idx, hash, hashSz);
idx += hashSz;
cookie[idx++] = ssl->options.cipherSuite0;
cookie[idx++] = ssl->options.cipherSuite;
if ((ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE)) != NULL) {
KeyShareEntry* kse = (KeyShareEntry*)ext->data;
c16toa(kse->group, cookie + idx);
idx += OPAQUE16_LEN;
}
return CreateCookie(ssl, cookie, idx);
}
#endif
ret = InitHandshakeHashes(ssl);
if (ret != 0)
return ret;
ret = HashOutputRaw(ssl, header, sizeof(header));
if (ret != 0)
return ret;
return HashOutputRaw(ssl, hash, hashSz);
}
#endif
/* Parse and handle a HelloRetryRequest message.
* Only a client will receive this message.
*
@ -3059,6 +3116,154 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
}
#endif
#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE)
/* Check that the Cookie data's integrity.
*
* ssl SSL/TLS object.
* cookie The cookie data - hash and MAC.
* cookieSz The length of the cookie data in bytes.
* returns Length of the hash on success, otherwise failure.
*/
static int CheckCookie(WOLFSSL* ssl, byte* cookie, byte cookieSz)
{
int ret;
byte mac[MAX_DIGEST_SIZE];
Hmac cookieHmac;
byte cookieType;
byte macSz;
#if !defined(NO_SHA) && defined(NO_SHA256)
cookieType = SHA;
macSz = SHA_DIGEST_SIZE;
#endif /* NO_SHA */
#ifndef NO_SHA256
cookieType = SHA256;
macSz = SHA256_DIGEST_SIZE;
#endif /* NO_SHA256 */
if (cookieSz < ssl->specs.hash_size + macSz)
return HRR_COOKIE_ERROR;
cookieSz -= macSz;
ret = wc_HmacSetKey(&cookieHmac, cookieType,
ssl->buffers.tls13CookieSecret.buffer,
ssl->buffers.tls13CookieSecret.length);
if (ret != 0)
return ret;
if ((ret = wc_HmacUpdate(&cookieHmac, cookie, cookieSz)) != 0)
return ret;
if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
return ret;
if (ConstantCompare(cookie + cookieSz, mac, macSz) != 0)
return HRR_COOKIE_ERROR;
return cookieSz;
}
/* Length of the KeyShare Extension */
#define HRR_KEY_SHARE_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
/* Length of the Cookie Extension excluding cookie data */
#define HRR_COOKIE_HDR_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
/* PV | CipherSuite | Ext Len */
#define HRR_BODY_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN)
/* HH | PV | CipherSuite | Ext Len | Key Share | Cookie */
#define MAX_HRR_SZ (HANDSHAKE_HEADER_SZ + \
HRR_BODY_SZ + \
HRR_KEY_SHARE_SZ + \
HRR_COOKIE_HDR_SZ)
/* Restart the Hanshake hash from the cookie value.
*
* ssl SSL/TLS object.
* cookie Cookie data from client.
* returns 0 on success, otherwise failure.
*/
static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie)
{
byte header[HANDSHAKE_HEADER_SZ];
byte hrr[MAX_HRR_SZ];
int hrrIdx;
word32 idx;
byte hashSz;
byte* cookieData;
byte cookieDataSz;
word16 length;
int keyShareExt = 0;
int ret;
cookieDataSz = ret = CheckCookie(ssl, &cookie->data, cookie->len);
if (ret < 0)
return ret;
hashSz = cookie->data;
cookieData = &cookie->data;
idx = OPAQUE8_LEN;
/* Restart handshake hash with synthetic message hash. */
AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl);
if ((ret = InitHandshakeHashes(ssl)) != 0)
return ret;
if ((ret = HashOutputRaw(ssl, header, sizeof(header))) != 0)
return ret;
if ((ret = HashOutputRaw(ssl, cookieData + idx, hashSz)) != 0)
return ret;
/* Reconstruct the HelloRetryMessage for handshake hash. */
length = HRR_BODY_SZ + HRR_COOKIE_HDR_SZ + cookie->len;
if (cookieDataSz > hashSz + OPAQUE16_LEN) {
keyShareExt = 1;
length += HRR_KEY_SHARE_SZ;
}
AddTls13HandShakeHeader(hrr, length, 0, 0, hello_retry_request, ssl);
idx += hashSz;
hrrIdx = HANDSHAKE_HEADER_SZ;
/* TODO: [TLS13] Replace existing code with code in comment.
* Use the TLS v1.3 draft version for now.
*
* Change to:
* hrr[hrrIdx++] = ssl->version.major;
* hrr[hrrIdx++] = ssl->version.minor;
*/
/* The negotiated protocol version. */
hrr[hrrIdx++] = TLS_DRAFT_MAJOR;
hrr[hrrIdx++] = TLS_DRAFT_MINOR;
/* Cipher Suite */
hrr[hrrIdx++] = cookieData[idx++];
hrr[hrrIdx++] = cookieData[idx++];
/* Extensions' length */
length -= HRR_BODY_SZ;
c16toa(length, hrr + hrrIdx);
hrrIdx += 2;
/* Optional KeyShare Extension */
if (keyShareExt) {
c16toa(TLSX_KEY_SHARE, hrr + hrrIdx);
hrrIdx += 2;
c16toa(OPAQUE16_LEN, hrr + hrrIdx);
hrrIdx += 2;
hrr[hrrIdx++] = cookieData[idx++];
hrr[hrrIdx++] = cookieData[idx++];
}
/* Mandatory Cookie Extension */
c16toa(TLSX_COOKIE, hrr + hrrIdx);
hrrIdx += 2;
c16toa(cookie->len + OPAQUE16_LEN, hrr + hrrIdx);
hrrIdx += 2;
c16toa(cookie->len, hrr + hrrIdx);
hrrIdx += 2;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Reconstucted HelloRetryRequest");
WOLFSSL_BUFFER(hrr, hrrIdx);
WOLFSSL_MSG("Cookie");
WOLFSSL_BUFFER(cookieData, cookie->len);
#endif
if ((ret = HashOutputRaw(ssl, hrr, hrrIdx)) != 0)
return ret;
return HashOutputRaw(ssl, cookieData, cookie->len);
}
#endif
/* Handle a ClientHello handshake message.
* If the protocol version in the message is not TLS v1.3 or higher, use
* DoClientHello()
@ -3182,6 +3387,23 @@ static int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL)
ssl->version.minor = pv.minor;
#ifdef WOLFSSL_SEND_HRR_COOKIE
if (ssl->options.sendCookie &&
ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) {
TLSX* ext;
if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL)
return HRR_COOKIE_ERROR;
/* Ensure the cookie came from client and isn't the one in the response
* - HelloRetryRequest.
*/
if (ext->resp == 1)
return HRR_COOKIE_ERROR;
ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data);
if (ret != 0)
return ret;
}
#endif
ssl->options.sendVerify = SEND_CERT;
@ -3244,6 +3466,11 @@ int SendTls13HelloRetryRequest(WOLFSSL* ssl)
WOLFSSL_ENTER("SendTls13HelloRetryRequest");
#ifndef WOLFSSL_TLS13_DRAFT_18
if ((ret = RestartHandshakeHash(ssl)) < 0)
return ret;
#endif
/* Get the length of the extensions that will be written. */
len = TLSX_GetResponseSize(ssl, hello_retry_request);
/* There must be extensions sent to indicate what client needs to do. */
@ -3294,11 +3521,6 @@ int SendTls13HelloRetryRequest(WOLFSSL* ssl)
}
#endif
#ifndef WOLFSSL_TLS13_DRAFT_18
if ((ret = RestartHandshakeHash(ssl)) < 0)
return ret;
#endif
if ((ret = HashOutput(ssl, output, idx, 0)) != 0)
return ret;
@ -3504,6 +3726,9 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
int sendSz;
word32 i;
int reqSz;
#ifndef WOLFSSL_TLS13_DRAFT_18
TLSX* ext;
#endif
WOLFSSL_ENTER("SendTls13CertificateRequest");
@ -3549,9 +3774,12 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
c16toa(0, &output[i]); /* auth's */
i += REQ_HEADER_SZ;
#else
ext = TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS);
ext->resp = 0;
i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
reqSz = OPAQUE8_LEN + reqCtxLen +
TLSX_GetResponseSize(ssl, certificate_request);
TLSX_GetRequestSize(ssl, certificate_request);
sendSz = i + reqSz;
/* Always encrypted and make room for padding. */
@ -3576,7 +3804,7 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
}
/* Certificate extensions. */
i += TLSX_WriteResponse(ssl, output + i, certificate_request);
i += TLSX_WriteRequest(ssl, output + i, certificate_request);
#endif
/* Always encrypted. */
@ -6060,7 +6288,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ret == 0 && type != client_hello && type != session_ticket &&
type != key_update && ssl->error != WC_PENDING_E) {
type != key_update && ssl->error != WC_PENDING_E) {
ret = HashInput(ssl, input + inIdx, size);
}
@ -6446,6 +6674,72 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
}
}
#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
/* Send a cookie with the HelloRetryRequest to avoid storing state.
*
* ssl SSL/TLS object.
* secret Secret to use when generating integrity check for cookie.
* A value of NULL indicates to generate a new random secret.
* secretSz Size of secret data in bytes.
* Use a value of 0 to indicate use of default size.
* returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or called on a
* client; SSL_SUCCESS on success and otherwise failure.
*/
int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, const unsigned char* secret,
unsigned int secretSz)
{
int ret;
if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version) ||
ssl->options.side == WOLFSSL_CLIENT_END)
return BAD_FUNC_ARG;
if (secretSz == 0) {
#if !defined(NO_SHA) && defined(NO_SHA256)
secretSz = SHA_DIGEST_SIZE;
#endif /* NO_SHA */
#ifndef NO_SHA256
secretSz = SHA256_DIGEST_SIZE;
#endif /* NO_SHA256 */
}
if (secretSz != ssl->buffers.tls13CookieSecret.length) {
byte* newSecret;
if (ssl->buffers.tls13CookieSecret.buffer != NULL) {
ForceZero(ssl->buffers.tls13CookieSecret.buffer,
ssl->buffers.tls13CookieSecret.length);
XFREE(ssl->buffers.tls13CookieSecret.buffer,
ssl->heap, DYNAMIC_TYPE_COOKIE_PWD);
}
newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD);
if (newSecret == NULL) {
ssl->buffers.tls13CookieSecret.buffer = NULL;
ssl->buffers.tls13CookieSecret.length = 0;
WOLFSSL_MSG("couldn't allocate new cookie secret");
return MEMORY_ERROR;
}
ssl->buffers.tls13CookieSecret.buffer = newSecret;
ssl->buffers.tls13CookieSecret.length = secretSz;
}
/* If the supplied secret is NULL, randomly generate a new secret. */
if (secret == NULL) {
ret = wc_RNG_GenerateBlock(ssl->rng,
ssl->buffers.tls13CookieSecret.buffer, secretSz);
if (ret < 0)
return ret;
}
else
XMEMCPY(ssl->buffers.tls13CookieSecret.buffer, secret, secretSz);
ssl->options.sendCookie = 1;
return SSL_SUCCESS;
}
#endif
/* Create a key share entry from group.
* Generates a key pair.
*

View File

@ -168,7 +168,8 @@ enum wolfSSL_ErrorCodes {
MATCH_SUITE_ERROR = -501, /* can't match cipher suite */
COMPRESSION_ERROR = -502, /* compression mismatch */
KEY_SHARE_ERROR = -503, /* key share mismatch */
POST_HAND_AUTH_ERROR = -504 /* client won't do post-hand auth */
POST_HAND_AUTH_ERROR = -504, /* client won't do post-hand auth */
HRR_COOKIE_ERROR = -505 /* HRR msg cookie mismatch */
/* end negotiation parameter errors only 10 for now */
/* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */

View File

@ -1789,6 +1789,7 @@ typedef enum {
TLSX_EARLY_DATA = 0x002a,
#endif
TLSX_SUPPORTED_VERSIONS = 0x002b,
TLSX_COOKIE = 0x002c,
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TLSX_PSK_KEY_EXCHANGE_MODES = 0x002d,
#endif
@ -1813,8 +1814,9 @@ WOLFSSL_LOCAL int TLSX_SupportExtensions(WOLFSSL* ssl);
WOLFSSL_LOCAL int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest);
#ifndef NO_WOLFSSL_CLIENT
WOLFSSL_LOCAL word16 TLSX_GetRequestSize(WOLFSSL* ssl);
WOLFSSL_LOCAL word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output);
WOLFSSL_LOCAL word16 TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType);
WOLFSSL_LOCAL word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output,
byte msgType);
#endif
#ifndef NO_WOLFSSL_SERVER
@ -2063,6 +2065,16 @@ WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name);
#endif /* HAVE_QSH */
#ifdef WOLFSSL_TLS13
/* Cookie extension information - cookie data. */
typedef struct Cookie {
word16 len;
byte data;
} Cookie;
WOLFSSL_LOCAL int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len,
byte* mac, byte macSz, int resp);
/* Key Share - TLS v1.3 Specification */
/* The KeyShare extension information - entry in a linked list. */
@ -2080,6 +2092,7 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len,
WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl);
WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl);
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
/* The PreSharedKey extension information - entry in a linked list. */
typedef struct PreSharedKey {
@ -2106,6 +2119,7 @@ WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity,
byte resumption,
PreSharedKey **preSharedKey);
/* The possible Pre-Shared Key key exchange modes. */
enum PskKeyExchangeMode {
PSK_KE,
PSK_DHE_KE
@ -2123,6 +2137,7 @@ WOLFSSL_LOCAL int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max);
#endif
#endif /* HAVE_SESSION_TICKET || !NO_PSK */
/* The types of keys to derive for. */
enum DeriveKeyType {
no_key,
@ -2196,13 +2211,13 @@ struct WOLFSSL_CTX {
byte groupMessages; /* group handshake messages before sending */
byte minDowngrade; /* minimum downgrade version */
byte haveEMS; /* have extended master secret extension */
byte useClientOrder; /* Use client's cipher preference order */
byte useClientOrder:1; /* Use client's cipher preference order */
#ifdef WOLFSSL_TLS13
byte noTicketTls13; /* Server won't create new Ticket */
byte noPskDheKe; /* Don't use (EC)DHE with PSK */
byte noTicketTls13:1; /* Server won't create new Ticket */
byte noPskDheKe:1; /* Don't use (EC)DHE with PSK */
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
byte postHandshakeAuth;/* Post-handshake authentication supported. */
byte postHandshakeAuth:1; /* Post-handshake auth supported. */
#endif
#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
byte dtlsSctp; /* DTLS-over-SCTP mode */
@ -2676,6 +2691,9 @@ typedef struct Buffers {
int certChainCnt;
#endif
#endif
#ifdef WOLFSSL_SEND_HRR_COOKIE
buffer tls13CookieSecret; /* HRR cookie secret */
#endif
#ifdef WOLFSSL_DTLS
WOLFSSL_DTLS_CTX dtlsCtx; /* DTLS connection context */
#ifndef NO_WOLFSSL_SERVER
@ -2808,6 +2826,9 @@ typedef struct Options {
word16 postHandshakeAuth:1;/* Client send post_handshake_auth
* extendion. */
#endif
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
word16 sendCookie:1; /* Server creates a Cookie in HRR */
#endif
/* need full byte values for this section */
byte processReply; /* nonblocking resume */

View File

@ -404,6 +404,8 @@ WOLFSSL_API int wolfSSL_read(WOLFSSL*, void*, int);
WOLFSSL_API int wolfSSL_peek(WOLFSSL*, void*, int);
WOLFSSL_API int wolfSSL_accept(WOLFSSL*);
#ifdef WOLFSSL_TLS13
WOLFSSL_API int wolfSSL_send_hrr_cookie(WOLFSSL* ssl,
const unsigned char* secret, unsigned int secretSz);
WOLFSSL_API int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx);
WOLFSSL_API int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx);