From e1373f0c9d6917fdf4160101c395095bfca17e1d Mon Sep 17 00:00:00 2001 From: Colton Willey Date: Tue, 5 May 2026 12:11:16 -0700 Subject: [PATCH] Fix X509 load locations to handle PEM files with multiple certs Adds X509LoadPemFile to walk multi-cert PEM files when loading via wolfSSL_X509_STORE_load_locations and X509_LOOKUP_load_file, replacing the single-cert helpers X509StoreReadFile/X509StoreLoadFile which only read the first cert from a file. Rebased fresh onto current upstream master (was 2209 commits behind); test additions deferred to a follow-up since the test file layout has been reorganized in master. --- src/x509.c | 49 ++++++++++++++++---------- src/x509_str.c | 86 ++-------------------------------------------- wolfssl/internal.h | 1 + 3 files changed, 34 insertions(+), 102 deletions(-) diff --git a/src/x509.c b/src/x509.c index a901a9aa515..ce179d4d246 100644 --- a/src/x509.c +++ b/src/x509.c @@ -8289,19 +8289,7 @@ const char* wolfSSL_X509_verify_cert_error_string(long err) #ifdef OPENSSL_EXTRA -/* Add directory path that will be used for loading certs and CRLs - * which have the .rn name format. - * type may be WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. - * returns WOLFSSL_SUCCESS on successful, otherwise negative or zero. */ -int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir, - long type) -{ - return wolfSSL_X509_LOOKUP_ctrl(lookup, WOLFSSL_X509_L_ADD_DIR, dir, type, - NULL); -} - -int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, - const char* file, long type) +int X509LoadPemFile(WOLFSSL_X509_STORE *store, const char* file) { #if !defined(NO_FILESYSTEM) && \ (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) @@ -8314,9 +8302,6 @@ int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, const char* header = NULL; const char* footer = NULL; - if (type != WOLFSSL_FILETYPE_PEM) - return WS_RETURN_CODE(BAD_FUNC_ARG, (int)WOLFSSL_FAILURE); - fp = XFOPEN(file, "rb"); if (fp == XBADFILE) return WS_RETURN_CODE(BAD_FUNC_ARG, (int)WOLFSSL_FAILURE); @@ -8352,7 +8337,7 @@ int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 && XSTRNSTR((char*)curr, header, sz) != NULL) { #ifdef HAVE_CRL - WOLFSSL_CERT_MANAGER* cm = lookup->store->cm; + WOLFSSL_CERT_MANAGER* cm = store->cm; if (cm->crl == NULL) { if (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) @@ -8370,7 +8355,7 @@ int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, curr = (byte*)XSTRNSTR((char*)curr, footer, sz); } else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 && - XSTRNSTR((char*)curr, header, sz) != NULL) { + XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) { ret = X509StoreLoadCertBuffer(lookup->store, curr, (word32)sz, WOLFSSL_FILETYPE_PEM); if (ret != WOLFSSL_SUCCESS) @@ -8393,6 +8378,34 @@ int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, XFREE(pem, 0, DYNAMIC_TYPE_PEM); XFCLOSE(fp); return WS_RETURN_CODE(ret, (int)WOLFSSL_FAILURE); +#else + (void)store; + (void)file; + return WS_RETURN_CODE(WOLFSSL_FAILURE,WOLFSSL_FAILURE); +#endif +} + +/* Add directory path that will be used for loading certs and CRLs + * which have the .rn name format. + * type may be WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * returns WOLFSSL_SUCCESS on successful, otherwise negative or zero. */ +int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir, + long type) +{ + return wolfSSL_X509_LOOKUP_ctrl(lookup, WOLFSSL_X509_L_ADD_DIR, dir, type, + NULL); +} + +int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, + const char* file, long type) +{ +#if !defined(NO_FILESYSTEM) && \ + (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) + + if (type != WOLFSSL_FILETYPE_PEM) + return WS_RETURN_CODE(BAD_FUNC_ARG, (int)WOLFSSL_FAILURE); + + return X509LoadPemFile(lookup->store, file); #else (void)lookup; (void)file; diff --git a/src/x509_str.c b/src/x509_str.c index 09870cb4382..6ed3f04670c 100644 --- a/src/x509_str.c +++ b/src/x509_str.c @@ -1891,74 +1891,6 @@ int X509StoreLoadCertBuffer(WOLFSSL_X509_STORE *str, #if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) -static int X509StoreReadFile(const char *fname, - StaticBuffer *content, word32 *bytesRead, int *type) -{ - int ret = -1; - long sz = 0; -#ifdef HAVE_CRL - const char* header = NULL; - const char* footer = NULL; -#endif - - ret = wolfssl_read_file_static(fname, content, NULL, DYNAMIC_TYPE_FILE, - &sz); - if (ret == 0) { - *type = CERT_TYPE; - *bytesRead = (word32)sz; -#ifdef HAVE_CRL - /* Look for CRL header and footer. */ - if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 && - (XSTRNSTR((char*)content->buffer, header, sz) != - NULL)) { - *type = CRL_TYPE; - } -#endif - } - - return (ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE); -} - -static int X509StoreLoadFile(WOLFSSL_X509_STORE *str, - const char *fname) -{ - int ret = WOLFSSL_SUCCESS; - int type = 0; -#ifndef WOLFSSL_SMALL_STACK - byte stackBuffer[FILE_BUFFER_SIZE]; -#endif - StaticBuffer content; - word32 contentLen = 0; - -#ifdef WOLFSSL_SMALL_STACK - static_buffer_init(&content); -#else - static_buffer_init(&content, stackBuffer, FILE_BUFFER_SIZE); -#endif - - WOLFSSL_MSG_EX("X509StoreLoadFile: Loading file: %s", fname); - - ret = X509StoreReadFile(fname, &content, &contentLen, &type); - if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Failed to load file"); - ret = WOLFSSL_FAILURE; - } - - if ((ret == WOLFSSL_SUCCESS) && (type == CERT_TYPE)) { - ret = X509StoreLoadCertBuffer(str, content.buffer, - contentLen, WOLFSSL_FILETYPE_PEM); - } -#ifdef HAVE_CRL - else if ((ret == WOLFSSL_SUCCESS) && (type == CRL_TYPE)) { - ret = BufferLoadCRL(str->cm->crl, content.buffer, contentLen, - WOLFSSL_FILETYPE_PEM, 0); - } -#endif - - static_buffer_free(&content, NULL, DYNAMIC_TYPE_FILE); - return ret; -} - /* Loads certificate(s) files in pem format into X509_STORE struct from either * a file or directory. * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE if an error occurs. @@ -1984,23 +1916,9 @@ int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, wolfSSL_CertManagerFree(ctx->cm); ctx->cm = str->cm; -#ifdef HAVE_CRL - if (str->cm->crl == NULL) { - /* Workaround to allocate the internals to load CRL's but don't enable - * CRL checking by default */ - if (wolfSSL_CertManagerEnableCRL(str->cm, WOLFSSL_CRL_CHECK) - != WOLFSSL_SUCCESS || - wolfSSL_CertManagerDisableCRL(str->cm) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Enable CRL failed"); - wolfSSL_CTX_free(ctx); - return WOLFSSL_FAILURE; - } - } -#endif - /* Load individual file */ if (file) { - ret = X509StoreLoadFile(str, file); + ret = X509LoadPemFile(str, file); if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Failed to load file"); ret = WOLFSSL_FAILURE; @@ -2026,7 +1944,7 @@ int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, while (ret == 0 && name) { WOLFSSL_MSG(name); - ret = X509StoreLoadFile(str, name); + ret = X509LoadPemFile(str, name); /* Not failing on load errors */ if (ret != WOLFSSL_SUCCESS) WOLFSSL_MSG("Failed to load file in path, continuing"); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 398f6b9ae71..99f07134fe8 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2748,6 +2748,7 @@ WOLFSSL_LOCAL void CleanupStoreCtxCallback(WOLFSSL_X509_STORE_CTX* store, WOLFSSL_LOCAL int X509StoreLoadCertBuffer(WOLFSSL_X509_STORE *str, byte *buf, word32 bufLen, int type); WOLFSSL_LOCAL int X509StorePushCertsToCM(WOLFSSL_X509_STORE* store); +WOLFSSL_LOCAL int X509LoadPemFile(WOLFSSL_X509_STORE *str, const char* file); #endif /* !defined NO_CERTS */ /* wolfSSL Sock Addr */