Skip to content

Instantly share code, notes, and snippets.

@jedisct1
Created April 14, 2026 16:06
Show Gist options
  • Select an option

  • Save jedisct1/d3280c4139c42a7212e7e6f082b90e2e to your computer and use it in GitHub Desktop.

Select an option

Save jedisct1/d3280c4139c42a7212e7e6f082b90e2e to your computer and use it in GitHub Desktop.

ASN1 UINTEGER decoder truncates oversized lengths

Classification

  • Type: vulnerability
  • Severity: high
  • Confidence: certain

Affected Locations

  • crypto/asn1/a_int.c:448
  • crypto/asn1/a_int.c:457
  • crypto/asn1/a_int.c:461
  • crypto/asn1/asn1_lib.c:46
  • crypto/asn1/asn1_lib.c:153

Summary

d2i_ASN1_UINTEGER() now casts a parsed ASN.1 content length from long to int without bounds checking, allowing oversized INTEGER lengths to truncate before allocation, copy, and stored length assignment.

Provenance

This exploration and report were automatically generated by the Swival Security Scanner (https://swival.dev).

Preconditions

  • A reachable decode path calls d2i_ASN1_UINTEGER() on attacker-controlled or malformed ASN.1 input.
  • The ASN.1 INTEGER uses a definite content length greater than INT_MAX but still representable as long on the target build.

Proof

  1. crypto/asn1/asn1_lib.c:46 parses ASN.1 object lengths into a long, and crypto/asn1/asn1_lib.c:139-crypto/asn1/asn1_lib.c:153 accepts any definite length up to LONG_MAX.
  2. crypto/asn1/a_int.c:440-crypto/asn1/a_int.c:443 reject only negative lengths. The prior INT_MAX guard present on the reference branch is absent in committed HEAD.
  3. crypto/asn1/a_int.c:448 allocates with OPENSSL_malloc((int)len + 1), crypto/asn1/a_int.c:457 copies with memcpy(s, p, (int)len), and crypto/asn1/a_int.c:461 stores the truncated length with ASN1_STRING_set0(ret, s, (int)len).
  4. For any parsed len > INT_MAX, each cast to int truncates the true content length before memory allocation and before the decoded object records its size.
  5. This violates the decoder invariant that the allocated buffer and stored ASN.1 string length match the parsed ASN.1 length, creating a concrete memory-safety and data-integrity failure on reachable oversized inputs.

Why This Is A Real Bug

The bug is directly visible in committed source and does not depend on speculation. The decoder explicitly accepts long lengths from the ASN.1 parser, then narrows them unsafely. The reference branch previously contained the exact missing guard, confirming this is a real regression rather than intentional behavior.

Fix Requirement

A code change is required because the current implementation mishandles valid parsed lengths that exceed INT_MAX. The decoder must reject lengths it cannot represent safely in the downstream int-based allocation and storage APIs.

Patch Rationale

The patch restores the lost INT_MAX bound check and uses size_t for allocation and copy sizes, matching the previous safe logic. It is minimal, local to the affected decoder, and preserves behavior for all representable ASN.1 INTEGER lengths.

Residual Risk

None

Patch

Reference: audit-findings/002-asn1-uinteger-length-truncation.patch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment