Skip to content

fix: heap-buffer-overflow READ in wolfSSL_i2c_ASN1_INTEGER via CRL revoked serial#10798

Open
MarkAtwood wants to merge 1 commit into
wolfSSL:masterfrom
MarkAtwood:fix/crl-serial-i2c-asn1int-oob
Open

fix: heap-buffer-overflow READ in wolfSSL_i2c_ASN1_INTEGER via CRL revoked serial#10798
MarkAtwood wants to merge 1 commit into
wolfSSL:masterfrom
MarkAtwood:fix/crl-serial-i2c-asn1int-oob

Conversation

@MarkAtwood

Copy link
Copy Markdown
Contributor

RevokedCertToRevoked() (src/x509.c) copies raw serial content bytes into serial->data and sets dataMax = serialSz. wolfSSL_i2c_ASN1_INTEGER() (src/ssl_asn1.c) assumes data[0] is the DER tag byte and data[1] is the length byte, then calls GetLength_ex with check=0 (no bounds enforcement). A crafted CRL with a serial whose second byte is large (e.g. 0x7f) causes XMEMCPY to read far past the end of the allocation.

Attack path — no signature verification required:

d2i_X509_CRL (NO_VERIFY) → X509_CRL_get_REVOKED → RevokedCertToRevoked
  → X509_REVOKED_get0_serialNumber → i2c_ASN1_INTEGER → OOB READ

Confirmed with ASAN: READ of size 127 from a 4-byte heap region (ssl_asn1.c:1711), wolfSSL 5.9.2 HEAD.

Fix 1 (root cause) — src/x509.c: prepend ASN_INTEGER tag and length byte to serial->data; allocate serialSz + 2 and set dataMax = serialSz + 2, matching the layout i2c_ASN1_INTEGER expects.

Fix 2 (defense-in-depth) — src/ssl_asn1.c: pass check=1 to GetLength_ex so bounds are enforced regardless of caller.

All 9 smoke-test configs pass (sanitize-asan, enable-all, opensslextra, default, etc.).

RevokedCertToRevoked() stored raw serial content bytes in
serial->data with dataMax=serialSz, but wolfSSL_i2c_ASN1_INTEGER
assumes data[0] is the DER tag byte and data[1] is the length byte.
GetLength_ex with check=0 then used data[1] as a length without bounds
enforcement, allowing an attacker-controlled CRL to trigger an OOB
heap read via X509_CRL_get_REVOKED + i2c_ASN1_INTEGER.

Fix 1 (root cause): prepend ASN_INTEGER tag and serialSz length byte
to serial->data in RevokedCertToRevoked; allocate serialSz+2 bytes
and set dataMax=serialSz+2 to match the expected layout.

Fix 2 (defense-in-depth): pass check=1 to GetLength_ex in
wolfSSL_i2c_ASN1_INTEGER so bounds are enforced even for
callers that pass a malformed ASN1_INTEGER.

Confirmed via ASAN PoC: READ of size 127 from 4-byte region no
longer fires after this patch.
Copilot AI review requested due to automatic review settings June 27, 2026 02:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an ASAN-confirmed heap-buffer-overflow read in the OpenSSL-compat CRL revoked-serial handling by ensuring WOLFSSL_ASN1_INTEGER data is formatted as the downstream encoder expects, and by enabling bounds checks during DER length parsing.

Changes:

  • src/x509.c: Build rev->serialNumber as DER (tag + length + value) instead of copying raw serial bytes.
  • src/ssl_asn1.c: Enable bounds enforcement in wolfSSL_i2c_ASN1_INTEGER() by calling GetLength_ex(..., check=1).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/x509.c Prepends DER tag/length to revoked serial number buffer to match wolfSSL_i2c_ASN1_INTEGER() expectations.
src/ssl_asn1.c Turns on defensive bounds checking when decoding DER length in wolfSSL_i2c_ASN1_INTEGER().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/x509.c
Comment on lines +11026 to +11030
serial->data[0] = ASN_INTEGER;
serial->data[1] = (unsigned char)rc->serialSz;
XMEMCPY(serial->data + 2, rc->serialNumber, (size_t)rc->serialSz);
serial->length = rc->serialSz;
serial->dataMax = rc->serialSz;
serial->dataMax = (word32)rc->serialSz + 2;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants