Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
5 changes: 3 additions & 2 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -26208,7 +26208,8 @@ int SendCertificateStatus(WOLFSSL* ssl)
}

if (chain && chain->buffer) {
while (ret == 0 && idx + OPAQUE24_LEN < chain->length) {
while (ret == 0 && i < MAX_CHAIN_DEPTH &&
idx + OPAQUE24_LEN < chain->length) {
c24to32(chain->buffer + idx, &der.length);
idx += OPAQUE24_LEN;

Expand Down Expand Up @@ -26249,7 +26250,7 @@ int SendCertificateStatus(WOLFSSL* ssl)
WC_FREE_VAR_EX(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
}
else {
while (ret == 0 &&
while (ret == 0 && i < MAX_CHAIN_DEPTH &&
NULL != (request = ssl->ctx->chainOcspRequest[i])) {
if ((i + 1) >= MAX_CERT_EXTENSIONS) {
ret = MAX_CERT_EXTENSIONS_ERR;
Expand Down
6 changes: 3 additions & 3 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -14121,7 +14121,7 @@ int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain)
int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
{
WOLFSSL_ENTER("wolfSSL_get_chain_length");
if (chain)
if (chain && idx >= 0 && idx < chain->count)
return chain->certs[idx].length;

return 0;
Expand All @@ -14132,7 +14132,7 @@ int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx)
{
WOLFSSL_ENTER("wolfSSL_get_chain_cert");
if (chain)
if (chain && idx >= 0 && idx < chain->count)
return chain->certs[idx].buffer;

return 0;
Expand All @@ -14147,7 +14147,7 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
WC_DECLARE_VAR(cert, DecodedCert, 1, 0);

WOLFSSL_ENTER("wolfSSL_get_chain_X509");
if (chain != NULL && idx < MAX_CHAIN_DEPTH) {
if (chain != NULL && idx >= 0 && idx < chain->count) {
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
DYNAMIC_TYPE_DCERT);
Expand Down
7 changes: 7 additions & 0 deletions src/ssl_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,13 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
while ((ret == 0) && (consumed < sz)) {
DerBuffer* part = NULL;

/* Enforce maximum chain depth. */
Comment thread
dgarske marked this conversation as resolved.
Outdated
if (cnt >= MAX_CHAIN_DEPTH) {
WOLFSSL_MSG("Chain depth limit reached");
ret = MAX_CHAIN_ERROR;
break;
}

/* Get a certificate as DER. */
ret = DataToDerBuffer(buff + consumed, (word32)(sz - consumed),
format, type, info, heap, &part, NULL);
Expand Down
8 changes: 7 additions & 1 deletion src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -2826,6 +2826,9 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
ato16(clientHello + offset, &listLen);
offset += OPAQUE16_LEN;

if (listLen != extLen - OPAQUE16_LEN)
return BUFFER_ERROR;

if (helloSz < offset + listLen)
return BUFFER_ERROR;

Expand All @@ -2836,6 +2839,9 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
ato16(clientHello + offset, &sniLen);
offset += OPAQUE16_LEN;

if (sniLen > listLen - (ENUM_LEN + OPAQUE16_LEN))
return BUFFER_ERROR;

if (helloSz < offset + sniLen)
return BUFFER_ERROR;

Expand Down Expand Up @@ -3393,7 +3399,7 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap)

switch (csr->status_type) {
case WOLFSSL_CSR_OCSP:
for (i = 0; i <= csr->requests; i++) {
for (i = 0; i < csr->requests; i++) {
FreeOcspRequest(&csr->request.ocsp[i]);
}
break;
Expand Down
4 changes: 4 additions & 0 deletions src/tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -9520,6 +9520,10 @@ static int SendTls13Certificate(WOLFSSL* ssl)
}
/* Certificate Data */
certSz = ssl->buffers.certificate->length;
if (ssl->buffers.certChainCnt > MAX_CHAIN_DEPTH) {
Comment thread
dgarske marked this conversation as resolved.
WOLFSSL_MSG("Certificate chain count exceeds maximum depth");
return MAX_CHAIN_ERROR;
}
/* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */
headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ +
CERT_HEADER_SZ;
Expand Down
85 changes: 85 additions & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -3828,6 +3828,89 @@ static int test_wolfSSL_CTX_use_certificate_chain_buffer_format(void)
return EXPECT_RESULT();
}

/* wolfSSL_get_chain_{length,cert,X509} must reject out-of-range idx. */
static int test_wolfSSL_get_chain_idx_bounds(void)
{
EXPECT_DECLS;
#if defined(SESSION_CERTS) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)
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_X509_CHAIN* chain = NULL;
int count;

XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLS_client_method, wolfTLS_server_method), 0);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);

ExpectNotNull(chain = wolfSSL_get_peer_chain(ssl_c));
ExpectIntGT(count = wolfSSL_get_chain_count(chain), 0);

ExpectIntEQ(wolfSSL_get_chain_length(chain, -1), 0);
ExpectIntEQ(wolfSSL_get_chain_length(chain, count), 0);
ExpectIntEQ(wolfSSL_get_chain_length(chain, MAX_CHAIN_DEPTH), 0);
ExpectNull(wolfSSL_get_chain_cert(chain, -1));
ExpectNull(wolfSSL_get_chain_cert(chain, count));
ExpectNull(wolfSSL_get_chain_cert(chain, MAX_CHAIN_DEPTH));
#ifdef OPENSSL_EXTRA
{
WOLFSSL_X509* x = NULL;
ExpectNull(x = wolfSSL_get_chain_X509(chain, -1));
if (x != NULL) { wolfSSL_X509_free(x); x = NULL; }
ExpectNull(x = wolfSSL_get_chain_X509(chain, count));
if (x != NULL) { wolfSSL_X509_free(x); x = NULL; }
ExpectNull(x = wolfSSL_get_chain_X509(chain, MAX_CHAIN_DEPTH));
Comment thread
douzzer marked this conversation as resolved.
if (x != NULL) { wolfSSL_X509_free(x); x = NULL; }
}
#endif

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

/* Reject chain buffers containing more than MAX_CHAIN_DEPTH certificates. */
static int test_wolfSSL_CTX_use_certificate_chain_buffer_max_depth(void)
{
EXPECT_DECLS;
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_RSA) && \
defined(WOLFSSL_PEM_TO_DER)
WOLFSSL_CTX* ctx = NULL;
unsigned char* one = NULL;
unsigned char* big = NULL;
size_t oneLen = 0;
size_t bigLen;
int i;
const int nCerts = MAX_CHAIN_DEPTH + 1;

ExpectIntEQ(load_file(svrCertFile, &one, &oneLen), 0);
bigLen = oneLen * (size_t)nCerts;
ExpectNotNull(big = (unsigned char*)XMALLOC(bigLen, NULL,
DYNAMIC_TYPE_TMP_BUFFER));
for (i = 0; EXPECT_SUCCESS() && i < nCerts; i++)
XMEMCPY(big + (size_t)i * oneLen, one, oneLen);

ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer(ctx, big,
(long)bigLen), WC_NO_ERR_TRACE(MAX_CHAIN_ERROR));

wolfSSL_CTX_free(ctx);
if (big != NULL)
XFREE(big, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (one != NULL)
XFREE(one, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}

static int test_wolfSSL_CTX_use_certificate_chain_file_format(void)
{
EXPECT_DECLS;
Expand Down Expand Up @@ -40648,6 +40731,8 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_CTX_add1_chain_cert),
TEST_DECL(test_wolfSSL_add_to_chain_overflow),
TEST_DECL(test_wolfSSL_CTX_use_certificate_chain_buffer_format),
TEST_DECL(test_wolfSSL_CTX_use_certificate_chain_buffer_max_depth),
TEST_DECL(test_wolfSSL_get_chain_idx_bounds),
TEST_DECL(test_wolfSSL_CTX_use_certificate_chain_file_format),
TEST_DECL(test_wolfSSL_use_certificate_chain_file),
TEST_DECL(test_wolfSSL_CTX_trust_peer_cert),
Expand Down
95 changes: 0 additions & 95 deletions tests/api/test_dtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -3158,101 +3158,6 @@ int test_dtls13_5_9_0_compat(void)
return EXPECT_RESULT();
}

/* Test that a DTLS 1.3 handshake with an oversized certificate chain does
Comment thread
ColtonWilley marked this conversation as resolved.
Outdated
* not crash or cause out-of-bounds access in SendTls13Certificate. */
int test_dtls13_oversized_cert_chain(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \
&& !defined(NO_FILESYSTEM) && !defined(NO_RSA)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
XFILE f = XBADFILE;
long sz = 0;
byte *cert = NULL;
byte *chain = NULL;
int copies, off, i;

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

/* Read server cert */
f = XFOPEN(svrCertFile, "rb");
ExpectTrue(f != XBADFILE);
if (EXPECT_SUCCESS()) {
(void)XFSEEK(f, 0, XSEEK_END);
sz = XFTELL(f);
(void)XFSEEK(f, 0, XSEEK_SET);
}
ExpectTrue(sz > 0);
cert = (byte*)XMALLOC((size_t)(sz + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(cert);
if (EXPECT_SUCCESS())
ExpectIntEQ((int)XFREAD(cert, 1, (size_t)sz, f), (int)sz);
if (f != XBADFILE)
XFCLOSE(f);

/* Build an oversized chain by duplicating the cert */
copies = EXPECT_SUCCESS() ? (int)(70000 / sz) + 2 : 0;
chain = (byte*)XMALLOC((size_t)(sz * copies + 1), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(chain);
off = 0;
if (EXPECT_SUCCESS()) {
for (i = 0; i < copies; i++) {
XMEMCPY(chain + off, cert, (size_t)sz);
off += (int)sz;
}
}

/* Server context: load the oversized chain */
ExpectNotNull(ctx_s = wolfSSL_CTX_new(wolfDTLSv1_3_server_method()));
ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer(ctx_s,
chain, (long)off), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx_s, svrKeyFile,
WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
if (EXPECT_SUCCESS()) {
wolfSSL_SetIORecv(ctx_s, test_memio_read_cb);
wolfSSL_SetIOSend(ctx_s, test_memio_write_cb);
}

/* Client context: no verification (chain certs are duplicates) */
ExpectNotNull(ctx_c = wolfSSL_CTX_new(wolfDTLSv1_3_client_method()));
if (EXPECT_SUCCESS()) {
wolfSSL_CTX_set_verify(ctx_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_SetIORecv(ctx_c, test_memio_read_cb);
wolfSSL_SetIOSend(ctx_c, test_memio_write_cb);
}

ExpectNotNull(ssl_s = wolfSSL_new(ctx_s));
if (EXPECT_SUCCESS()) {
wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx);
wolfSSL_SetIOReadCtx(ssl_s, &test_ctx);
}

ExpectNotNull(ssl_c = wolfSSL_new(ctx_c));
if (EXPECT_SUCCESS()) {
wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx);
wolfSSL_SetIOReadCtx(ssl_c, &test_ctx);
}

/* Handshake must not crash. If SendTls13Certificate mishandles the
* oversized chain this will trigger a wild pointer dereference or stack
* overflow resulting with the test failing.
* The correct behaviour either returns BUFFER_E or succeeds
* if the build config truncated the chain during loading. */
(void)test_memio_do_handshake(ssl_c, ssl_s, 10, NULL);

wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(chain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}

/* DTLS counterpart to test_tls_set_session_min_downgrade. Exercises the
* inverted DTLS minor-version comparison (DTLS 1.2 minor 0xFD is "below"
* floor 0xFC = DTLS 1.3). */
Expand Down
2 changes: 0 additions & 2 deletions tests/api/test_dtls.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ int test_dtls_mtu_split_messages(void);
int test_dtls13_min_rtx_interval(void);
int test_dtls13_no_session_id_echo(void);
int test_dtls13_5_9_0_compat(void);
int test_dtls13_oversized_cert_chain(void);
int test_dtls_set_session_min_downgrade(void);

#define TEST_DTLS_DECLS \
Expand Down Expand Up @@ -93,7 +92,6 @@ int test_dtls_set_session_min_downgrade(void);
TEST_DECL_GROUP("dtls", test_dtls_memio_wolfio_stateless), \
TEST_DECL_GROUP("dtls", test_dtls13_min_rtx_interval), \
TEST_DECL_GROUP("dtls", test_dtls13_no_session_id_echo), \
TEST_DECL_GROUP("dtls", test_dtls13_oversized_cert_chain), \
TEST_DECL_GROUP("dtls", test_dtls_set_session_min_downgrade), \
TEST_DECL_GROUP("dtls", test_dtls13_5_9_0_compat)
#endif /* TESTS_API_DTLS_H */
59 changes: 59 additions & 0 deletions tests/api/test_pkcs7.c
Original file line number Diff line number Diff line change
Expand Up @@ -2873,6 +2873,65 @@ int test_wc_PKCS7_DecodeEnvelopedData_forgedRecipientSetLen(void)
} /* END test_wc_PKCS7_DecodeEnvelopedData_forgedRecipientSetLen() */


/* Decoding an AuthEnvelopedData blob whose encryptedContent or authTag
* is truncated must return BUFFER_E rather than reading past pkiMsg. */
int test_wc_PKCS7_DecodeAuthEnvelopedData_truncated(void)
{
EXPECT_DECLS;
#if defined(HAVE_PKCS7) && defined(HAVE_AESGCM) && !defined(NO_RSA) && \
!defined(NO_AES) && defined(WOLFSSL_AES_128) && defined(NO_PKCS7_STREAM)
PKCS7* pkcs7 = NULL;
byte enveloped[2048];
byte decoded[256];
byte data[] = "truncated authEnvelopedData test";
int encSz = 0;

ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)client_cert_der_2048,
sizeof_client_cert_der_2048), 0);
if (pkcs7 != NULL) {
pkcs7->content = data;
pkcs7->contentSz = (word32)sizeof(data);
pkcs7->contentOID = DATA;
pkcs7->encryptOID = AES128GCMb;
}
ExpectIntGT(encSz = wc_PKCS7_EncodeAuthEnvelopedData(pkcs7, enveloped,
sizeof(enveloped)), 0);
wc_PKCS7_Free(pkcs7);
pkcs7 = NULL;

/* Truncate inside encryptedContent (encryptedContentSz check). */
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)client_cert_der_2048,
sizeof_client_cert_der_2048), 0);
if (pkcs7 != NULL) {
pkcs7->privateKey = (byte*)client_key_der_2048;
pkcs7->privateKeySz = sizeof_client_key_der_2048;
}
ExpectIntEQ(wc_PKCS7_DecodeAuthEnvelopedData(pkcs7, enveloped,
(word32)encSz - 32, decoded, sizeof(decoded)),
WC_NO_ERR_TRACE(BUFFER_E));
wc_PKCS7_Free(pkcs7);
pkcs7 = NULL;
Comment thread
ColtonWilley marked this conversation as resolved.
Comment thread
ColtonWilley marked this conversation as resolved.

/* Truncate one byte off the auth tag (authTagSz check). */
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)client_cert_der_2048,
sizeof_client_cert_der_2048), 0);
if (pkcs7 != NULL) {
pkcs7->privateKey = (byte*)client_key_der_2048;
pkcs7->privateKeySz = sizeof_client_key_der_2048;
}
ExpectIntEQ(wc_PKCS7_DecodeAuthEnvelopedData(pkcs7, enveloped,
(word32)encSz - 1, decoded, sizeof(decoded)),
WC_NO_ERR_TRACE(BUFFER_E));

wc_PKCS7_Free(pkcs7);
#endif
return EXPECT_RESULT();
} /* END test_wc_PKCS7_DecodeAuthEnvelopedData_truncated() */


/*
* Testing wc_PKCS7_DecodeEnvelopedData with streaming
*/
Expand Down
Loading
Loading