ASN1_PARSE_DUMP(3)

πŸ“¦
version 4.4.0 Β· 2 versions
, in arch rolling

πŸ’… ASN1_PARSE_DUMP(3) β€” Library Functions Manual

okay bestie, so this one is a libcrypto page (yes, from that library) and it's all about poking at BER blobs and printing out what's inside them. it's giving "forensics but make it cute" πŸ”βœ¨


✨ NAME ✨

ASN1_parse_dump, ASN1_parse β€” parse BER and print information about it


πŸŽ€ SYNOPSIS πŸŽ€

library β€œlibcrypto” #include <openssl/asn1.h>

int
ASN1_parse_dump(BIO *bio, const unsigned char *ber_in, long length,
    int indent, int dump);

int
ASN1_parse(BIO *bio, const unsigned char *ber_in, long length,
    int indent);

πŸ¦‹ DESCRIPTION πŸ¦‹

So ASN1_parse_dump() parses BER-encoded values and prints info about them to bio. When you call it, *ber_in is supposed to point at the first identifier octet of an encoded value. It only looks at at most length bytes. no more, no cap, literally capped πŸ“

For every value it successfully parses, it prints these lil facts:

  1. The index of its first identifier octet, counted relative to ber_in, as a decimal number followed by a colon. For the very first value parsed and printed, that's 0: πŸ’«
  2. The nesting depth as a decimal integer. For the first value parsed and printed, that's d=0. we love a clean start 🫢
  3. The header length in bytes β€” identifier octets + length octets β€” as a decimal integer. Example: for a boolean value this is hl=2, because a boolean's encoding has one identifier octet (0x01) and one length octet (also 0x01, since exactly one content octet follows the header).
  4. If the value uses the definite form for its length octets, the number encoded in those length octets, as a decimal integer. That's how many content octets follow. Example: for a boolean value, that's l=1. If instead the length octet is doing the indefinite-form thing, it prints l=inf instead. infinity era ♾️
  5. If the value is primitive, it prints prim:; if it's constructed, cons:. (yes those are the whole labels, she's concise πŸ’…)
  6. The next field depends on the class of the tag:
    • V_ASN1_PRIVATE β€” priv followed by the decimal tag number in square brackets
    • V_ASN1_CONTEXT_SPECIFIC β€” cont followed by the decimal tag number in square brackets
    • V_ASN1_APPLICATION β€” appl followed by the decimal tag number in square brackets
    • V_ASN1_UNIVERSAL β€” if the tag number is 30 or less, it prints whatever ASN1_tag2str(3) returns; otherwise it prints <ASN1 followed by the decimal tag number and a closing angle bracket

For constructed values, the contained values get recursively printed. it's giving nesting dolls πŸͺ†

Primitive values get processed like this:

  • V_ASN1_BOOLEAN β€” its integer value is printed as a decimal number.
  • V_ASN1_INTEGER β€” decoded with d2i_ASN1_INTEGER(3), then printed as a hexadecimal number with an even number of digits.
  • V_ASN1_ENUMERATED β€” decoded with d2i_ASN1_ENUMERATED(3), then printed as a hexadecimal number with an even number of digits.
  • V_ASN1_OBJECT β€” decoded with d2i_ASN1_OBJECT(3), then printed with i2a_ASN1_OBJECT(3).
  • V_ASN1_OCTET_STRING β€” decoded with d2i_ASN1_OCTET_STRING(3). If the data is only printable ASCII characters, line feeds, carriage returns and horizontal tabs, it's printed as an ASCII string. 🌸 Otherwise the dump argument picks the format. If it's zero, you get a raw hex dump β€” two hexadecimal digits for every data byte. If dump is non-zero, BIO_dump_indent(3) is used instead. And unless dump is -1, the data gets truncated after dump bytes. (so -1 is the "no truncation, we die like women" setting 😭)
  • V_ASN1_PRINTABLESTRING β€” printed as an ASCII string. Same deal applies to V_ASN1_IA5STRING, V_ASN1_T61STRING, V_ASN1_NUMERICSTRING, V_ASN1_VISIBLESTRING, V_ASN1_UTF8STRING, V_ASN1_UTCTIME, and V_ASN1_GENERALIZEDTIME.
  • Other tags β€” if dump is 0, their data is silently ignored (not a word, just vibes 🀐). If dump is non-zero, BIO_dump_indent(3) is used. Unless dump is -1, the data gets truncated after dump bytes.

And ASN1_parse() is literally identical to ASN1_parse_dump() except it passes 0 as the dump argument. twins πŸ‘―β€β™€οΈ


πŸ”₯ RETURN VALUES πŸ”₯

These functions normally return 1 for success or 0 for failure. BUT β€” plot twist β€” when printing indefinite-length encoded BER with a tag of class V_ASN1_UNIVERSAL, a return value of 2 means the printing stopped because it hit the end-of-content marker. iconic behavior honestly πŸ‘‘

Specifically, they print an error message to bio, abort parsing and printing, and return 0 when:

  • parsing or decoding fails
  • a recursive call fails
  • they hit a value extending beyond length
  • they hit a nesting level in excess of 128 (we have limits, bestie πŸ’€)
  • any printing operation fails β€” that also aborts parsing and printing and returns 0

🌈 SEE ALSO 🌈

ASN1_get_object(3), ASN1_item_d2i(3), ASN1_item_new(3), ASN1_STRING_print(3), ASN1_TYPE_new(3)


⭐ STANDARDS ⭐

ITU-T Recommendation X.690, also known as ISO/IEC 8825-1: Information technology - ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER), section 8.1: General rules for encoding ✨


πŸ’œ HISTORY πŸ’œ

ASN1_parse() first appeared in SSLeay 0.5.1 and has been available since OpenBSD 2.4. an elder, respect her 🫑

ASN1_parse_dump() first appeared in OpenSSL 0.9.6 and has been available since OpenBSD 2.9.


πŸ™ˆ BUGS πŸ™ˆ

The content of values tagged as V_ASN1_BMPSTRING is silently ignored and none of it is printed. like… where did it go. nobody knows. not me, not you, not the BMPSTRING πŸ’€


so yeah, that's the whole page β€” brought to you by Debian, dated May 16, 2026, in section 3 of the manual (yes, ASN1_PARSE_DUMP(3)), and honestly? she ate. πŸ“πŸ§š go parse something and slay πŸ’–

πŸ“¦ where this page comes from
  • arch rolling: libressl 4.4.0-1 Β· ISC AND custom:OpenSSL
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms