diff --git a/src/ssl.c b/src/ssl.c index 5569cae7f..e27ae8d72 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -4263,15 +4263,16 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif byte* chainBuffer = staticBuffer; int dynamicBuffer = 0; - word32 bufferSz = sizeof(staticBuffer); + word32 bufferSz; long consumed = info->consumed; word32 idx = 0; int gotOne = 0; - if ( (sz - consumed) > (int)bufferSz) { + /* Calculate max possible size, including max headers */ + bufferSz = (word32)(sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH); + if (bufferSz > sizeof(staticBuffer)) { WOLFSSL_MSG("Growing Tmp Chain Buffer"); - bufferSz = (word32)(sz - consumed); - /* will shrink to actual size */ + /* will shrink to actual size */ chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE); if (chainBuffer == NULL) { return MEMORY_E; @@ -4301,7 +4302,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, if (GetSequence(buff + consumed, &inOutIdx, &length, remain) < 0) { ret = ASN_NO_PEM_HEADER; } - length += inOutIdx; /* include leading squence */ + length += inOutIdx; /* include leading sequence */ } info->consumed = length; if (ret == 0) { @@ -4316,7 +4317,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, #ifdef WOLFSSL_TLS13 cnt++; #endif - if ((idx + part->length) > bufferSz) { + if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) { WOLFSSL_MSG(" Cert Chain bigger than buffer"); ret = BUFFER_E; } @@ -4446,7 +4447,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (GetSequence(buff, &inOutIdx, &length, (word32)sz) < 0) { ret = ASN_PARSE_E; } - length += inOutIdx; /* include leading squence */ + length += inOutIdx; /* include leading sequence */ } info->consumed = length; @@ -4465,6 +4466,10 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, /* process user chain */ if (ret >= 0) { + /* First certificate in chain is loaded into ssl->buffers.certificate. + * Remainder are loaded into ssl->buffers.certChain. + * Chain should have server cert first, then intermediates, then root. + */ if (userChain) { ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info); } diff --git a/tests/api.c b/tests/api.c index 7307e629b..afc45d8c3 100644 --- a/tests/api.c +++ b/tests/api.c @@ -721,6 +721,25 @@ static void test_wolfSSL_CTX_load_verify_locations(void) #endif } + +static int test_wolfSSL_CTX_use_certificate_chain_file_format(void) +{ + int ret = 0; +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) + const char* server_chain_der = "./certs/server-cert-chain.der"; + WOLFSSL_CTX* ctx; + + ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + AssertNotNull(ctx); + + AssertIntEQ(wolfSSL_CTX_use_certificate_chain_file_format(ctx, + server_chain_der, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + + wolfSSL_CTX_free(ctx); +#endif + return ret; +} + static void test_wolfSSL_CTX_SetTmpDH_file(void) { #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_DH) && \ @@ -19906,6 +19925,7 @@ void ApiTest(void) AssertIntEQ(test_wolfSSL_CTX_use_certificate_buffer(), WOLFSSL_SUCCESS); test_wolfSSL_CTX_use_PrivateKey_file(); test_wolfSSL_CTX_load_verify_locations(); + test_wolfSSL_CTX_use_certificate_chain_file_format(); test_wolfSSL_CTX_trust_peer_cert(); test_wolfSSL_CTX_SetTmpDH_file(); test_wolfSSL_CTX_SetTmpDH_buffer();