Skip to content

Commit 90584f2

Browse files
committed
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.
1 parent 1c9555c commit 90584f2

4 files changed

Lines changed: 89 additions & 28 deletions

File tree

src/x509.c

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13499,36 +13499,35 @@ WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
1349913499
WOLFSSL_X509_CRL **x, wc_pem_password_cb *cb, void *u)
1350013500
{
1350113501
#if defined(WOLFSSL_PEM_TO_DER) && defined(HAVE_CRL)
13502-
unsigned char* pem = NULL;
13503-
int pemSz = 0;
13504-
int derSz = 0;
13505-
DerBuffer* der = NULL;
1350613502
WOLFSSL_X509_CRL* crl = NULL;
1350713503

1350813504
WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509_CRL");
1350913505

13510-
if ((pem = ReadPemFromBioToBuffer(bp, &pemSz)) == NULL) {
13511-
goto err;
13512-
}
13513-
13514-
if ((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0) {
13515-
goto err;
13516-
}
13517-
derSz = (int)der->length;
13518-
if ((crl = wolfSSL_d2i_X509_CRL(x, der->buffer, derSz)) == NULL) {
13519-
goto err;
13506+
/* OpenSSL's PEM_read_bio_X509_CRL skips intervening cert/key blocks
13507+
* and returns the next CRL in the stream (NULL only at EOF). Mirror
13508+
* that by looping over the per-block reader until we get a CRL or
13509+
* the BIO has nothing left to parse. */
13510+
for (;;) {
13511+
WOLFSSL_X509* x509 = NULL;
13512+
WOLFSSL_X509_PKEY* x_pkey = NULL;
13513+
if (wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(bp, cb,
13514+
&x509, &crl, &x_pkey) != WOLFSSL_SUCCESS) {
13515+
break;
13516+
}
13517+
if (crl != NULL) {
13518+
break;
13519+
}
13520+
wolfSSL_X509_free(x509);
13521+
wolfSSL_X509_PKEY_free(x_pkey);
1352013522
}
1352113523

13522-
err:
13523-
if (pemSz == 0) {
13524-
WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
13525-
}
13526-
XFREE(pem, 0, DYNAMIC_TYPE_PEM);
13527-
if (der != NULL) {
13528-
FreeDer(&der);
13524+
if (x != NULL) {
13525+
if (*x != NULL && *x != crl) {
13526+
wolfSSL_X509_CRL_free(*x);
13527+
}
13528+
*x = crl;
1352913529
}
1353013530

13531-
(void)cb;
1353213531
(void)u;
1353313532

1353413533
return crl;
@@ -13691,7 +13690,7 @@ int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type)
1369113690
#endif /* !NO_FILESYSTEM */
1369213691

1369313692
#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
13694-
#ifdef OPENSSL_ALL
13693+
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
1369513694

1369613695
#ifndef NO_BIO
1369713696
/* 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)
1371113710

1371213711

1371313712
/* free up all memory used by "xPkey" passed in */
13714-
static void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey)
13713+
void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey)
1371513714
{
1371613715
if (xPkey != NULL) {
1371713716
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)
1373713736
* @param x_pkey Output
1373813737
* @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE otherwise
1373913738
*/
13740-
static int wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(
13739+
int wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(
1374113740
WOLFSSL_BIO* bio, wc_pem_password_cb* cb, WOLFSSL_X509** x509,
1374213741
WOLFSSL_X509_CRL** crl, WOLFSSL_X509_PKEY** x_pkey)
1374313742
{
@@ -13921,6 +13920,9 @@ int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type)
1392113920
#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
1392213921
}
1392313922

13923+
#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
13924+
#ifdef OPENSSL_ALL
13925+
1392413926
#ifndef NO_FILESYSTEM
1392513927
WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read(
1392613928
XFILE fp, WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
@@ -14058,7 +14060,7 @@ int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type)
1405814060
return localSk;
1405914061
}
1406014062
#endif /* !NO_BIO */
14061-
#endif /* OPENSSL_ALL */
14063+
#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
1406214064

1406314065
void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne)
1406414066
{

tests/api/test_ossl_x509_lu.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,17 @@ int test_wolfSSL_X509_load_crl_file(void)
312312
#endif
313313
""
314314
};
315+
int pemCount[] = {
316+
1,
317+
2,
318+
1,
319+
1,
320+
1,
321+
#ifdef WC_RSA_PSS
322+
1,
323+
#endif
324+
0
325+
};
315326
char der[][100] = {
316327
"./certs/crl/crl.der",
317328
"./certs/crl/crl2.der",
@@ -342,7 +353,7 @@ int test_wolfSSL_X509_load_crl_file(void)
342353
ExpectIntEQ(X509_load_crl_file(lookup, pem[0], 0), 0);
343354
for (i = 0; pem[i][0] != '\0'; i++) {
344355
ExpectIntEQ(X509_load_crl_file(lookup, pem[i], WOLFSSL_FILETYPE_PEM),
345-
1);
356+
pemCount[i]);
346357
}
347358

348359
if (store) {
@@ -394,6 +405,45 @@ int test_wolfSSL_X509_load_crl_file(void)
394405

395406
X509_STORE_free(store);
396407
store = NULL;
408+
409+
/* Combine crl.pem (1 CRL), a server cert, and crl2.pem (2 CRLs) into a
410+
* single memory BIO. wolfSSL_PEM_read_bio_X509_CRL must walk past the
411+
* intervening certificate and hand back all three CRLs before NULL,
412+
* matching OpenSSL's PEM_read_bio_X509_CRL behaviour. */
413+
{
414+
WOLFSSL_BIO* fileBio = NULL;
415+
WOLFSSL_BIO* memBio = NULL;
416+
WOLFSSL_X509_CRL* crl = NULL;
417+
unsigned char buf[4096];
418+
int n;
419+
int crlCount = 0;
420+
const char* sources[] = {
421+
"./certs/crl/crl.pem",
422+
"./certs/server-cert.pem",
423+
"./certs/crl/crl2.pem",
424+
NULL
425+
};
426+
427+
ExpectNotNull(memBio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()));
428+
for (i = 0; sources[i] != NULL; i++) {
429+
ExpectNotNull(fileBio = wolfSSL_BIO_new_file(sources[i], "rb"));
430+
while (fileBio != NULL &&
431+
(n = wolfSSL_BIO_read(fileBio, buf, sizeof(buf))) > 0) {
432+
ExpectIntEQ(wolfSSL_BIO_write(memBio, buf, n), n);
433+
}
434+
wolfSSL_BIO_free(fileBio);
435+
fileBio = NULL;
436+
}
437+
438+
while ((crl = wolfSSL_PEM_read_bio_X509_CRL(memBio, NULL, NULL, NULL))
439+
!= NULL) {
440+
crlCount++;
441+
wolfSSL_X509_CRL_free(crl);
442+
}
443+
ExpectIntEQ(crlCount, 3);
444+
445+
wolfSSL_BIO_free(memBio);
446+
}
397447
#endif
398448
return EXPECT_RESULT();
399449
}

tests/api/test_ossl_x509_lu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ int test_X509_LOOKUP_add_dir(void);
3434
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_LOOKUP_load_file), \
3535
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_LOOKUP_ctrl_file), \
3636
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_LOOKUP_ctrl_hash_dir), \
37-
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_LOOKUP_ctrl_hash_dir), \
37+
TEST_DECL_GROUP("ossl_x509_lu", test_wolfSSL_X509_load_crl_file), \
3838
TEST_DECL_GROUP("ossl_x509_lu", test_X509_LOOKUP_add_dir)
3939

4040
#endif /* WOLFCRYPT_TEST_OSSL_X509_LU_H */

wolfssl/internal.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7469,6 +7469,15 @@ WOLFSSL_LOCAL int pkcs8_encrypt(WOLFSSL_EVP_PKEY* pkey,
74697469
word32* keySz);
74707470
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
74717471

7472+
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_BIO)
7473+
WOLFSSL_LOCAL int wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(
7474+
WOLFSSL_BIO* bio, wc_pem_password_cb* cb, WOLFSSL_X509** x509,
7475+
WOLFSSL_X509_CRL** crl, WOLFSSL_X509_PKEY** x_pkey);
7476+
#endif
7477+
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
7478+
WOLFSSL_LOCAL void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey);
7479+
#endif
7480+
74727481
WOLFSSL_LOCAL void wolfssl_local_MaybeCheckAlertOnErr(WOLFSSL* ssl, int err);
74737482

74747483
#ifdef __cplusplus

0 commit comments

Comments
 (0)