Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 99 additions & 30 deletions src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1809,16 +1809,20 @@ static void TLSX_ALPN_FreeAll(ALPN *list, void* heap)
static word16 TLSX_ALPN_GetSize(ALPN *list)
{
ALPN* alpn;
word16 length = OPAQUE16_LEN; /* list length */
word32 length = OPAQUE16_LEN; /* list length */

while ((alpn = list)) {
list = alpn->next;

length++; /* protocol name length is on one byte */
length += (word16)XSTRLEN(alpn->protocol_name);
length += (word32)XSTRLEN(alpn->protocol_name);

if (length > WOLFSSL_MAX_16BIT) {
return 0;
}
}

return length;
return (word16)length;
Comment thread
julek-wolfssl marked this conversation as resolved.
}

/** Writes the ALPN objects of a list in a buffer. */
Expand Down Expand Up @@ -2941,7 +2945,7 @@ static void TLSX_TCA_FreeAll(TCA* list, void* heap)
static word16 TLSX_TCA_GetSize(TCA* list)
{
TCA* tca;
word16 length = OPAQUE16_LEN; /* list length */
word32 length = OPAQUE16_LEN; /* list length */

while ((tca = list)) {
list = tca->next;
Expand All @@ -2959,9 +2963,13 @@ static word16 TLSX_TCA_GetSize(TCA* list)
length += OPAQUE16_LEN + tca->idSz;
break;
}

if (length > WOLFSSL_MAX_16BIT) {
return 0;
}
Comment thread
julek-wolfssl marked this conversation as resolved.
}

return length;
return (word16)length;
}

/** Writes the TCA objects of a list in a buffer. */
Expand Down Expand Up @@ -7568,7 +7576,7 @@ static word16 TLSX_CA_Names_GetSize(void* data)
{
WOLFSSL* ssl = (WOLFSSL*)data;
WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
word16 size = 0;
word32 size = 0;

/* Length of names */
size += OPAQUE16_LEN;
Expand All @@ -7578,11 +7586,14 @@ static word16 TLSX_CA_Names_GetSize(void* data)

if (name != NULL) {
/* 16-bit length | SEQ | Len | DER of name */
size += (word16)(OPAQUE16_LEN + SetSequence(name->rawLen, seq) +
size += (word32)(OPAQUE16_LEN + SetSequence(name->rawLen, seq) +
name->rawLen);
if (size > WOLFSSL_MAX_16BIT) {
return 0;
}
}
}
return size;
return (word16)size;
Comment thread
julek-wolfssl marked this conversation as resolved.
}

static word16 TLSX_CA_Names_Write(void* data, byte* output)
Expand Down Expand Up @@ -11903,14 +11914,22 @@ static int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType,
{
if (msgType == client_hello) {
/* Length of identities + Length of binders. */
word16 len = OPAQUE16_LEN + OPAQUE16_LEN;
word32 len = OPAQUE16_LEN + OPAQUE16_LEN;
while (list != NULL) {
/* Each entry has: identity, ticket age and binder. */
len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN +
OPAQUE8_LEN + (word16)list->binderLen;
OPAQUE8_LEN + (word32)list->binderLen;
if (len > WOLFSSL_MAX_16BIT) {
WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR);
return LENGTH_ERROR;
}
list = list->next;
}
*pSz += len;
if ((word32)*pSz + len > WOLFSSL_MAX_16BIT) {
WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR);
return LENGTH_ERROR;
}
*pSz += (word16)len;
return 0;
Comment thread
julek-wolfssl marked this conversation as resolved.
}

Expand All @@ -11933,7 +11952,7 @@ static int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType,
int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType,
word16* pSz)
{
word16 len;
word32 len;

if (msgType != client_hello) {
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
Expand All @@ -11943,11 +11962,15 @@ int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType,
/* Length of all binders. */
len = OPAQUE16_LEN;
while (list != NULL) {
len += OPAQUE8_LEN + (word16)list->binderLen;
len += OPAQUE8_LEN + (word32)list->binderLen;
if (len > WOLFSSL_MAX_16BIT) {
WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR);
return LENGTH_ERROR;
}
list = list->next;
}

*pSz = len;
*pSz = (word16)len;
return 0;
}

Expand Down Expand Up @@ -14850,10 +14873,15 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
{
int ret = 0;
TLSX* extension;
word16 length = 0;
/* Accumulate in word32 so per-extension additions can't silently wrap
* a word16 total - the final 16-bit bound is enforced once at the end. */
word32 length = 0;
word16 hsz;
byte isRequest = (msgType == client_hello ||
msgType == certificate_request);

(void)hsz;

while ((extension = list)) {
list = extension->next;

Expand Down Expand Up @@ -14884,8 +14912,15 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,

case TLSX_TRUSTED_CA_KEYS:
/* TCA only sends the list on the request. */
if (isRequest)
length += TCA_GET_SIZE((TCA*)extension->data);
if (isRequest) {
word16 tcaSz = TCA_GET_SIZE((TCA*)extension->data);
/* 0 on non-empty list means 16-bit overflow. */
if (tcaSz == 0 && extension->data != NULL) {
ret = LENGTH_ERROR;
break;
}
length += tcaSz;
}
Comment thread
julek-wolfssl marked this conversation as resolved.
break;

case TLSX_MAX_FRAGMENT_LENGTH:
Expand Down Expand Up @@ -14926,33 +14961,48 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
isRequest);
break;

case TLSX_APPLICATION_LAYER_PROTOCOL:
length += ALPN_GET_SIZE((ALPN*)extension->data);
case TLSX_APPLICATION_LAYER_PROTOCOL: {
word16 alpnSz = ALPN_GET_SIZE((ALPN*)extension->data);
/* 0 on non-empty list means 16-bit overflow. */
if (alpnSz == 0 && extension->data != NULL) {
ret = LENGTH_ERROR;
break;
}
length += alpnSz;
break;
}
#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
case TLSX_SIGNATURE_ALGORITHMS:
length += SA_GET_SIZE(extension->data);
break;
#endif
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
case TLSX_ENCRYPT_THEN_MAC:
ret = ETM_GET_SIZE(msgType, &length);
hsz = 0;
ret = ETM_GET_SIZE(msgType, &hsz);
length += hsz;
break;
#endif /* HAVE_ENCRYPT_THEN_MAC */

#if defined(WOLFSSL_TLS13) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
case TLSX_PRE_SHARED_KEY:
hsz = 0;
ret = PSK_GET_SIZE((PreSharedKey*)extension->data, msgType,
&length);
&hsz);
length += hsz;
break;
#ifdef WOLFSSL_TLS13
case TLSX_PSK_KEY_EXCHANGE_MODES:
ret = PKM_GET_SIZE((byte)extension->val, msgType, &length);
hsz = 0;
ret = PKM_GET_SIZE((byte)extension->val, msgType, &hsz);
length += hsz;
break;
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
case TLSX_CERT_WITH_EXTERN_PSK:
ret = PSK_WITH_CERT_GET_SIZE(msgType, &length);
hsz = 0;
ret = PSK_WITH_CERT_GET_SIZE(msgType, &hsz);
length += hsz;
break;
#endif
#endif
Expand All @@ -14964,22 +15014,30 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,

#ifdef WOLFSSL_TLS13
case TLSX_SUPPORTED_VERSIONS:
ret = SV_GET_SIZE(extension->data, msgType, &length);
hsz = 0;
ret = SV_GET_SIZE(extension->data, msgType, &hsz);
length += hsz;
break;

case TLSX_COOKIE:
ret = CKE_GET_SIZE((Cookie*)extension->data, msgType, &length);
hsz = 0;
ret = CKE_GET_SIZE((Cookie*)extension->data, msgType, &hsz);
length += hsz;
break;

#ifdef WOLFSSL_EARLY_DATA
case TLSX_EARLY_DATA:
ret = EDI_GET_SIZE(msgType, &length);
hsz = 0;
ret = EDI_GET_SIZE(msgType, &hsz);
length += hsz;
break;
#endif

#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
case TLSX_POST_HANDSHAKE_AUTH:
ret = PHA_GET_SIZE(msgType, &length);
hsz = 0;
ret = PHA_GET_SIZE(msgType, &hsz);
length += hsz;
break;
#endif

Expand All @@ -14990,9 +15048,16 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
#endif

#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
case TLSX_CERTIFICATE_AUTHORITIES:
length += CAN_GET_SIZE(extension->data);
case TLSX_CERTIFICATE_AUTHORITIES: {
word16 canSz = CAN_GET_SIZE(extension->data);
/* 0 on non-empty list means 16-bit overflow. */
if (canSz == 0 && extension->data != NULL) {
ret = LENGTH_ERROR;
break;
}
length += canSz;
break;
}
#endif
#endif
#ifdef WOLFSSL_SRTP
Expand Down Expand Up @@ -15037,7 +15102,11 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
TURN_ON(semaphore, TLSX_ToSemaphore((word16)extension->type));
}

*pLength += length;
if (ret == 0 && (word32)*pLength + length > WOLFSSL_MAX_16BIT) {
WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR);
return LENGTH_ERROR;
}
*pLength += (word16)length;

return ret;
}
Expand Down
79 changes: 79 additions & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -10436,6 +10436,78 @@ static int test_wolfSSL_SCR_check_enabled(void)
return EXPECT_RESULT();
}

/* F-2922: wolfSSL_TicketKeyCb must reject a session ticket whose HMAC
* does not match its encrypted contents. */
static int test_wolfSSL_ticket_keycb_bad_hmac(void)
{
EXPECT_DECLS;
#if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_TLS12) && \
defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) && \
defined(WOLFSSL_AES_256) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
!defined(WOLFSSL_NO_DEF_TICKET_ENC_CB)
struct test_memio_ctx test_ctx;
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
WOLFSSL_SESSION *session = NULL;

XMEMSET(&test_ctx, 0, sizeof(test_ctx));

ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);

ExpectIntEQ(OpenSSLTicketInit(), 0);
ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx_s,
myTicketEncCbOpenSSL), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_UseSessionTicket(ssl_c), WOLFSSL_SUCCESS);

ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
ExpectNotNull(session = wolfSSL_get1_session(ssl_c));
ExpectIntGT(session->ticketLen, 0);

/* Corrupt a byte of the ticket HMAC so the server's HMAC
* verification rejects it. */
if (session != NULL && session->ticket != NULL && session->ticketLen > 0)
session->ticket[session->ticketLen - 1] ^= 0xFF;

wolfSSL_free(ssl_c);
ssl_c = NULL;
wolfSSL_free(ssl_s);
ssl_s = NULL;
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);

ExpectNotNull(ssl_c = wolfSSL_new(ctx_c));
ExpectNotNull(ssl_s = wolfSSL_new(ctx_s));
wolfSSL_SetIOReadCtx(ssl_c, &test_ctx);
wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx);
wolfSSL_SetIOReadCtx(ssl_s, &test_ctx);
wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx);
ExpectIntEQ(wolfSSL_set_session(ssl_c, session), WOLFSSL_SUCCESS);
/* Disable the process-global session cache lookup on the server so that
* the ticket is the only resumption path - with WOLFSSL_TICKET_HAVE_ID
* the server could otherwise resume by session ID. */
if (ssl_s != NULL)
ssl_s->options.sessionCacheOff = 1;

/* Corrupted ticket bytes fail the HMAC check in
* wolfSSL_TicketKeyCb; the session must not resume. */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
ExpectIntEQ(wolfSSL_session_reused(ssl_c), 0);

wolfSSL_SESSION_free(session);
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
OpenSSLTicketCleanup();
#endif
return EXPECT_RESULT();
}


#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) && \
!defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC))
/* Called when writing. */
Expand Down Expand Up @@ -36298,6 +36370,12 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_select_next_proto),
#endif
TEST_DECL(test_tls_ems_downgrade),
TEST_DECL(test_tls_ems_resumption_downgrade),
TEST_DECL(test_tls12_chacha20_poly1305_bad_tag),
TEST_DECL(test_tls13_null_cipher_bad_hmac),
TEST_DECL(test_scr_verify_data_mismatch),
TEST_DECL(test_tls13_hrr_cipher_suite_mismatch),
TEST_DECL(test_tls13_ticket_age_out_of_window),
TEST_DECL(test_wolfSSL_DisableExtendedMasterSecret),
TEST_DECL(test_certificate_authorities_certificate_request),
TEST_DECL(test_certificate_authorities_client_hello),
Expand All @@ -36306,6 +36384,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
TEST_DECL(test_wolfSSL_SCR_Reconnect),
TEST_DECL(test_wolfSSL_SCR_check_enabled),
TEST_DECL(test_wolfSSL_ticket_keycb_bad_hmac),
TEST_DECL(test_tls_ext_duplicate),
TEST_DECL(test_tls_bad_legacy_version),
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
Expand Down
Loading
Loading