Skip to content

Commit 9b780e8

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. To make those helpers callable from the new 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) and declare both WOLFSSL_LOCAL in internal.h under their existing OPENSSL_ALL[/NO_BIO] gates. 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 9b780e8

4 files changed

Lines changed: 81 additions & 26 deletions

File tree

src/x509.c

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13499,36 +13499,32 @@ 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+
*x = crl;
1352913526
}
1353013527

13531-
(void)cb;
1353213528
(void)u;
1353313529

1353413530
return crl;
@@ -13711,7 +13707,7 @@ int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type)
1371113707

1371213708

1371313709
/* free up all memory used by "xPkey" passed in */
13714-
static void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey)
13710+
void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey)
1371513711
{
1371613712
if (xPkey != NULL) {
1371713713
wolfSSL_EVP_PKEY_free(xPkey->dec_pkey);
@@ -13737,7 +13733,7 @@ int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type)
1373713733
* @param x_pkey Output
1373813734
* @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE otherwise
1373913735
*/
13740-
static int wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(
13736+
int wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(
1374113737
WOLFSSL_BIO* bio, wc_pem_password_cb* cb, WOLFSSL_X509** x509,
1374213738
WOLFSSL_X509_CRL** crl, WOLFSSL_X509_PKEY** x_pkey)
1374313739
{

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_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+
#ifdef 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)