mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 10:50:53 +02:00
src/x509.c: refactor wolfSSL_PEM_read_bio_X509_CRL onto the per-block reader
ReadPemFromBioToBuffer slurps the entire BIO in one shot, so iterative
callers like wolfSSL_PEM_read_bio_X509_CRL (and by extension
wolfSSL_X509_load_crl_file's BIO branch) saw EOF after the first block
and silently dropped every CRL after the first in a multi-CRL bundle.
Refactor wolfSSL_PEM_read_bio_X509_CRL to delegate to
wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio, which already reads one
PEM BEGIN/END pair per call and leaves the BIO positioned just past the
END line. Loop over it so we skip past intervening cert/key blocks and
return the next CRL in the stream — matching OpenSSL's
PEM_read_bio_X509_CRL, verified against OpenSSL 3.0.13 with cases
{cert,CRL}, {CRL,cert}, {CRL,cert,CRL}, {key,CRL}, {CRL,key,CRL}: in
each case OpenSSL skips non-CRL blocks until EOF.
When the caller passes a non-NULL `x` whose `*x` is already populated,
free the previous CRL before overwriting the slot — matching the
d2i_X509_CRL reuse contract the old body relied on.
To keep both helpers visible at the new call site, drop their `static`
qualifier (wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio for the per-block
read, wolfSSL_X509_PKEY_free to free defensively-allocated keys parsed
from intervening non-CRL blocks). Their definitions in src/x509.c and
declarations in wolfssl/internal.h are widened from OPENSSL_ALL to
OPENSSL_EXTRA || OPENSSL_ALL so the OPENSSL_EXTRA-only build (which
compiles wolfSSL_PEM_read_bio_X509_CRL) links cleanly. The unrelated
INFO_read_bio / INFO_read_bio_X509_INFO group below them keeps its
OPENSSL_ALL gate because it depends on wolfSSL_X509_INFO_new/free that
are still OPENSSL_ALL-only.
Also register the previously-orphaned test_wolfSSL_X509_load_crl_file
(its slot in TEST_OSSL_X509_LOOKUP_DECLS was a duplicated
test_wolfSSL_X509_LOOKUP_ctrl_hash_dir entry), update its assertion for
crl2.pem (which already contains two CRLs) to expect 2 instead of 1, and
add a multi-CRL bundle case that builds a memory BIO from
crl.pem + server-cert.pem + crl2.pem and asserts that the reader walks
past the cert and returns all 3 CRLs before NULL.
This commit is contained in:
+28
-26
@@ -13499,36 +13499,35 @@ WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
|
||||
WOLFSSL_X509_CRL **x, wc_pem_password_cb *cb, void *u)
|
||||
{
|
||||
#if defined(WOLFSSL_PEM_TO_DER) && defined(HAVE_CRL)
|
||||
unsigned char* pem = NULL;
|
||||
int pemSz = 0;
|
||||
int derSz = 0;
|
||||
DerBuffer* der = NULL;
|
||||
WOLFSSL_X509_CRL* crl = NULL;
|
||||
|
||||
WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509_CRL");
|
||||
|
||||
if ((pem = ReadPemFromBioToBuffer(bp, &pemSz)) == NULL) {
|
||||
goto err;
|
||||
/* OpenSSL's PEM_read_bio_X509_CRL skips intervening cert/key blocks
|
||||
* and returns the next CRL in the stream (NULL only at EOF). Mirror
|
||||
* that by looping over the per-block reader until we get a CRL or
|
||||
* the BIO has nothing left to parse. */
|
||||
for (;;) {
|
||||
WOLFSSL_X509* x509 = NULL;
|
||||
WOLFSSL_X509_PKEY* x_pkey = NULL;
|
||||
if (wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(bp, cb,
|
||||
&x509, &crl, &x_pkey) != WOLFSSL_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
if (crl != NULL) {
|
||||
break;
|
||||
}
|
||||
wolfSSL_X509_free(x509);
|
||||
wolfSSL_X509_PKEY_free(x_pkey);
|
||||
}
|
||||
|
||||
if ((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0) {
|
||||
goto err;
|
||||
}
|
||||
derSz = (int)der->length;
|
||||
if ((crl = wolfSSL_d2i_X509_CRL(x, der->buffer, derSz)) == NULL) {
|
||||
goto err;
|
||||
if (x != NULL) {
|
||||
if (*x != NULL && *x != crl) {
|
||||
wolfSSL_X509_CRL_free(*x);
|
||||
}
|
||||
*x = crl;
|
||||
}
|
||||
|
||||
err:
|
||||
if (pemSz == 0) {
|
||||
WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
|
||||
}
|
||||
XFREE(pem, 0, DYNAMIC_TYPE_PEM);
|
||||
if (der != NULL) {
|
||||
FreeDer(&der);
|
||||
}
|
||||
|
||||
(void)cb;
|
||||
(void)u;
|
||||
|
||||
return crl;
|
||||
@@ -13691,7 +13690,7 @@ int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type)
|
||||
#endif /* !NO_FILESYSTEM */
|
||||
|
||||
#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
|
||||
#ifdef OPENSSL_ALL
|
||||
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
|
||||
|
||||
#ifndef NO_BIO
|
||||
/* create and return a new WOLFSSL_X509_PKEY structure or NULL on failure */
|
||||
@@ -13711,7 +13710,7 @@ int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type)
|
||||
|
||||
|
||||
/* free up all memory used by "xPkey" passed in */
|
||||
static void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey)
|
||||
void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey)
|
||||
{
|
||||
if (xPkey != NULL) {
|
||||
wolfSSL_EVP_PKEY_free(xPkey->dec_pkey);
|
||||
@@ -13737,7 +13736,7 @@ int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type)
|
||||
* @param x_pkey Output
|
||||
* @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE otherwise
|
||||
*/
|
||||
static int wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(
|
||||
int wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(
|
||||
WOLFSSL_BIO* bio, wc_pem_password_cb* cb, WOLFSSL_X509** x509,
|
||||
WOLFSSL_X509_CRL** crl, WOLFSSL_X509_PKEY** x_pkey)
|
||||
{
|
||||
@@ -13921,6 +13920,9 @@ err:
|
||||
#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
|
||||
}
|
||||
|
||||
#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
|
||||
#ifdef OPENSSL_ALL
|
||||
|
||||
#ifndef NO_FILESYSTEM
|
||||
WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read(
|
||||
XFILE fp, WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
|
||||
@@ -14058,7 +14060,7 @@ err:
|
||||
return localSk;
|
||||
}
|
||||
#endif /* !NO_BIO */
|
||||
#endif /* OPENSSL_ALL */
|
||||
#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
|
||||
|
||||
void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne)
|
||||
{
|
||||
|
||||
@@ -312,6 +312,17 @@ int test_wolfSSL_X509_load_crl_file(void)
|
||||
#endif
|
||||
""
|
||||
};
|
||||
int pemCount[] = {
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
#ifdef WC_RSA_PSS
|
||||
1,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
char der[][100] = {
|
||||
"./certs/crl/crl.der",
|
||||
"./certs/crl/crl2.der",
|
||||
@@ -342,7 +353,7 @@ int test_wolfSSL_X509_load_crl_file(void)
|
||||
ExpectIntEQ(X509_load_crl_file(lookup, pem[0], 0), 0);
|
||||
for (i = 0; pem[i][0] != '\0'; i++) {
|
||||
ExpectIntEQ(X509_load_crl_file(lookup, pem[i], WOLFSSL_FILETYPE_PEM),
|
||||
1);
|
||||
pemCount[i]);
|
||||
}
|
||||
|
||||
if (store) {
|
||||
@@ -394,6 +405,45 @@ int test_wolfSSL_X509_load_crl_file(void)
|
||||
|
||||
X509_STORE_free(store);
|
||||
store = NULL;
|
||||
|
||||
/* Combine crl.pem (1 CRL), a server cert, and crl2.pem (2 CRLs) into a
|
||||
* single memory BIO. wolfSSL_PEM_read_bio_X509_CRL must walk past the
|
||||
* intervening certificate and hand back all three CRLs before NULL,
|
||||
* matching OpenSSL's PEM_read_bio_X509_CRL behaviour. */
|
||||
{
|
||||
WOLFSSL_BIO* fileBio = NULL;
|
||||
WOLFSSL_BIO* memBio = NULL;
|
||||
WOLFSSL_X509_CRL* crl = NULL;
|
||||
unsigned char buf[4096];
|
||||
int n;
|
||||
int crlCount = 0;
|
||||
const char* sources[] = {
|
||||
"./certs/crl/crl.pem",
|
||||
"./certs/server-cert.pem",
|
||||
"./certs/crl/crl2.pem",
|
||||
NULL
|
||||
};
|
||||
|
||||
ExpectNotNull(memBio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()));
|
||||
for (i = 0; sources[i] != NULL; i++) {
|
||||
ExpectNotNull(fileBio = wolfSSL_BIO_new_file(sources[i], "rb"));
|
||||
while (fileBio != NULL &&
|
||||
(n = wolfSSL_BIO_read(fileBio, buf, sizeof(buf))) > 0) {
|
||||
ExpectIntEQ(wolfSSL_BIO_write(memBio, buf, n), n);
|
||||
}
|
||||
wolfSSL_BIO_free(fileBio);
|
||||
fileBio = NULL;
|
||||
}
|
||||
|
||||
while ((crl = wolfSSL_PEM_read_bio_X509_CRL(memBio, NULL, NULL, NULL))
|
||||
!= NULL) {
|
||||
crlCount++;
|
||||
wolfSSL_X509_CRL_free(crl);
|
||||
}
|
||||
ExpectIntEQ(crlCount, 3);
|
||||
|
||||
wolfSSL_BIO_free(memBio);
|
||||
}
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ int test_X509_LOOKUP_add_dir(void);
|
||||
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_LOOKUP_load_file), \
|
||||
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_LOOKUP_ctrl_file), \
|
||||
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_LOOKUP_ctrl_hash_dir), \
|
||||
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_LOOKUP_ctrl_hash_dir), \
|
||||
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_load_crl_file), \
|
||||
TEST_DECL_GROUP("ossl_x509_lu", test_X509_LOOKUP_add_dir)
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_OSSL_X509_LU_H */
|
||||
|
||||
@@ -7469,6 +7469,15 @@ WOLFSSL_LOCAL int pkcs8_encrypt(WOLFSSL_EVP_PKEY* pkey,
|
||||
word32* keySz);
|
||||
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
|
||||
|
||||
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_BIO)
|
||||
WOLFSSL_LOCAL int wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(
|
||||
WOLFSSL_BIO* bio, wc_pem_password_cb* cb, WOLFSSL_X509** x509,
|
||||
WOLFSSL_X509_CRL** crl, WOLFSSL_X509_PKEY** x_pkey);
|
||||
#endif
|
||||
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
|
||||
WOLFSSL_LOCAL void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey);
|
||||
#endif
|
||||
|
||||
WOLFSSL_LOCAL void wolfssl_local_MaybeCheckAlertOnErr(WOLFSSL* ssl, int err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user