ASN1_ITEM_D2I_BIO(3ossl)

✨ ASN1_ITEM_D2I_BIO πŸ’… β€” the OpenSSL 3ossl glow-up ✨

okay bestie, sit down, hydrate, and let me tell you about decoding and encoding DER-encoded ASN.1 structures πŸ¦‹ this page covers a whole little friend group of functions β€” ASN1_item_d2i_ex, ASN1_item_d2i, ASN1_item_d2i_bio_ex, ASN1_item_d2i_bio, ASN1_item_d2i_fp_ex, ASN1_item_d2i_fp, ASN1_item_i2d_mem_bio, ASN1_item_pack, ASN1_item_unpack_ex and ASN1_item_unpack β€” and yes, they're all iconic, no skips πŸ’–


🌸 NAME 🌸

ASN1_item_d2i_ex, ASN1_item_d2i, ASN1_item_d2i_bio_ex, ASN1_item_d2i_bio, ASN1_item_d2i_fp_ex, ASN1_item_d2i_fp, ASN1_item_i2d_mem_bio, ASN1_item_pack, ASN1_item_unpack_ex, ASN1_item_unpack β€” decode and encode DER-encoded ASN.1 structures πŸŽ€


🧚 SYNOPSIS 🧚

#include <openssl/asn1.h>

ASN1_VALUE *ASN1_item_d2i_ex(ASN1_VALUE **pval, const unsigned char **in,
                             long len, const ASN1_ITEM *it,
                             OSSL_LIB_CTX *libctx, const char *propq);
ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in,
                          long len, const ASN1_ITEM *it);

void *ASN1_item_d2i_bio_ex(const ASN1_ITEM *it, BIO *in, void *x,
                           OSSL_LIB_CTX *libctx, const char *propq);
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);

void *ASN1_item_d2i_fp_ex(const ASN1_ITEM *it, FILE *in, void *x,
                          OSSL_LIB_CTX *libctx, const char *propq);
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);

BIO *ASN1_item_i2d_mem_bio(const ASN1_ITEM *it, const ASN1_VALUE *val);

ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct);

void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it);

void *ASN1_item_unpack_ex(const ASN1_STRING *oct, const ASN1_ITEM *it,
                         OSSL_LIB_CTX *libctx, const char *propq);

πŸ’œ DESCRIPTION πŸ’œ

🫢 the d2i girls (decoding, going byte-by-byte)

ASN1_item_d2i_ex() decodes the contents of the data stored in *in, which has length len and must be a DER-encoded ASN.1 structure, using the ASN.1 template it. It places the result in *pval unless pval is NULL. And listen β€” if *pval is non-NULL on entry, the ASN1_VALUE already sitting there gets reused. Otherwise a brand new ASN1_VALUE gets allocated. Slay, no waste πŸ’…

If any algorithm fetches are required during the process, they'll use the OSSL_LIB_CTX provided in the libctx parameter and the property query string in propq. Want the whole lore on algorithm fetching? Go read "ALGORITHM FETCHING" in crypto(7) ✨

On exit, *in gets updated to point to the next byte in the buffer after the decoded structure. Moving on up, literally πŸ¦‹

ASN1_item_d2i() is the same as ASN1_item_d2i_ex() except the default OSSL_LIB_CTX is used (i.e. NULL) and it uses a NULL property query string. Same girl, simpler fit πŸŽ€

ASN1_item_d2i_bio_ex() decodes the contents of its input BIO in, which must be a DER-encoded ASN.1 structure, using the ASN.1 template it, and places the result in *pval unless pval is NULL. If in is NULL it returns NULL, else a pointer to the parsed structure. If any algorithm fetches are required during the process, they'll use the OSSL_LIB_CTX provided in the libctx parameter and the property query string in propq. Again: "ALGORITHM FETCHING" in crypto(7), go read it πŸ’–

When reading from in, decoding consumes one complete DER-encoded structure and leaves any following bytes in the BIO, so concatenated structures can be read with successive calls. Very "one at a time, bestie" of it 🌸

Reaching the end of the input cleanly, at a structure boundary, is not treated as an error: the function returns NULL without adding to the error queue. But if the end of the input is reached in the middle of a structure, or an indefinite-length value is missing its end-of-contents octets (that is, the input is truncated 😭), an error is queued with reason code ASN1_R_NOT_ENOUGH_DATA. The same applies to ASN1_item_d2i_fp_ex().

ASN1_item_d2i_bio() is the same as ASN1_item_d2i_bio_ex() except the default OSSL_LIB_CTX is used (i.e. NULL) and with a NULL property query string ✨

ASN1_item_d2i_fp_ex() is the same as ASN1_item_d2i_bio_ex() except a FILE pointer is provided instead of a BIO πŸ“

ASN1_item_d2i_fp() is the same as ASN1_item_d2i_fp_ex() except the default OSSL_LIB_CTX is used (i.e. NULL) and with a NULL property query string 🌈

πŸ‘‘ the i2d/pack/unpack girls (encoding & the reverse)

ASN1_item_i2d_mem_bio() encodes the given ASN.1 value val using the ASN.1 template it and returns the result in a memory BIO. Cute, contained, memory-based. Main character energy πŸ‘‘

ASN1_item_pack() encodes the given ASN.1 value in obj using the ASN.1 template it and returns an ASN1_STRING object. Now pay attention bestie, the pointer rules here are giving very specific:

  • If the passed in *oct is not NULL, then it's used to store the returned result.
  • Otherwise a new ASN1_STRING object is created.
  • If oct is not NULL and *oct is NULL, then the returned return is also set into *oct.
And if there's an error, the optional passed-in ASN1_STRING will not be freed β€” but the previous value may be cleared when ASN1_STRING_set0(*oct, NULL, 0) is called internally. Not me warning you about the sneaky internal clear πŸ™ˆ

ASN1_item_unpack() uses ASN1_item_d2i() to decode the DER-encoded ASN1_STRING oct using the ASN.1 template it πŸ’«

ASN1_item_unpack_ex() is similar to ASN1_item_unpack(), but uses ASN1_item_d2i_ex() so that the libctx and propq can be used when doing algorithm fetching. Fancy upgrade, same vibe πŸ’œ


πŸŽ€ RETURN VALUES πŸŽ€

ASN1_item_d2i_bio(), ASN1_item_unpack_ex() and ASN1_item_unpack() return a pointer to an ASN1_VALUE or NULL on error πŸ’€

The ASN1_item_d2i_bio() and ASN1_item_d2i_fp() functions, including their _ex variants, also return NULL at a clean end of input. In that case the error queue is left unchanged, so a caller reading concatenated structures in a loop can distinguish a clean end of input from a decoding error by inspecting the error queue, for example with ERR_peek_error(3). iykyk πŸ‘€

ASN1_item_i2d_mem_bio() returns a pointer to a memory BIO or NULL on error 🌸

ASN1_item_pack() returns a pointer to an ASN1_STRING or NULL on error πŸ¦‹


⭐ HISTORY ⭐

The functions ASN1_item_d2i_ex(), ASN1_item_d2i_bio_ex(), ASN1_item_d2i_fp_ex() and ASN1_item_i2d_mem_bio() were added in OpenSSL 3.0 ✨

The function ASN1_item_unpack_ex() was added in OpenSSL 3.2 πŸ’–


Copyright 2021-2026 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


and that's the whole page bestie, no cap πŸ’… this was the ASN1_ITEM_D2I_BIO(3ossl) manual from OpenSSL 3.5.9, dated 2026-09-29 β€” periodt, go decode something responsibly πŸ«ΆπŸŽ€

πŸ“¦ where this page comes from