ASN1_EXTERN_FUNCS(3ossl)

πŸ“¦ version 3.5.0, in opensuse-leap 16.0

πŸ’… ASN1_EXTERN_FUNCS β€” ASN.1 external function support (ossl, bestie)

okay so this is ASN1_EXTERN_FUNCS(3ossl), and it's literally the page about building ASN.1 templates out of your own functions instead of the usual macros. it's giving "custom build, DIY era" and honestly? we're obsessed πŸŽ€


✨ NAME ✨

ASN1_EXTERN_FUNCS, ASN1_ex_d2i, ASN1_ex_d2i_ex, ASN1_ex_i2d, ASN1_ex_new_func, ASN1_ex_new_ex_func, ASN1_ex_free_func, ASN1_ex_print_func, IMPLEMENT_EXTERN_ASN1 β€” all of these together = ASN.1 external function support πŸ¦‹


🌸 SYNOPSIS 🌸

#include <openssl/asn1t.h>

typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
                        const ASN1_ITEM *it, int tag, int aclass, char opt,
                        ASN1_TLC *ctx);
typedef int ASN1_ex_d2i_ex(ASN1_VALUE **pval, const unsigned char **in, long len,
                           const ASN1_ITEM *it, int tag, int aclass, char opt,
                           ASN1_TLC *ctx, OSSL_LIB_CTX *libctx,
                           const char *propq);
typedef int ASN1_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
                        const ASN1_ITEM *it, int tag, int aclass);
typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
typedef int ASN1_ex_new_ex_func(ASN1_VALUE **pval, const ASN1_ITEM *it,
                                OSSL_LIB_CTX *libctx, const char *propq);
typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
typedef int ASN1_ex_print_func(BIO *out, const ASN1_VALUE **pval,
                               int indent, const char *fname,
                               const ASN1_PCTX *pctx);

struct ASN1_EXTERN_FUNCS_st {
   void *app_data;
   ASN1_ex_new_func *asn1_ex_new;
   ASN1_ex_free_func *asn1_ex_free;
   ASN1_ex_free_func *asn1_ex_clear;
   ASN1_ex_d2i *asn1_ex_d2i;
   ASN1_ex_i2d *asn1_ex_i2d;
   ASN1_ex_print_func *asn1_ex_print;
   ASN1_ex_new_ex_func *asn1_ex_new_ex;
   ASN1_ex_d2i_ex *asn1_ex_d2i_ex;
};
typedef struct ASN1_EXTERN_FUNCS_st ASN1_EXTERN_FUNCS;

#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs)

like, that's the whole vibe right there 🫢


πŸ’– DESCRIPTION πŸ’–

so normally, ASN.1 data structure templates in OpenSSL get defined with a little parade of macros β€” ASN1_SEQUENCE(), ASN1_SEQUENCE_END(), the whole squad. but plot twist 🌈 β€” templates can also be defined entirely on top of external functions. and those external functions are the ones doing the actual work, like creating a new ASN1_VALUE, or converting an ASN1_VALUE to and from DER encoding.

the macro IMPLEMENT_EXTERN_ASN1() is how you build one of these externally defined structures. here's the trio of things you gotta feed it:

  • the name of the structure goes in the sname parameter πŸ‘‘
  • the tag for the structure (typically something like V_ASN1_SEQUENCE) goes in the tag parameter
  • a pointer to an ASN1_EXTERN_FUNCS structure goes in the fptrs parameter

and the ASN1_EXTERN_FUNCS structure has these entries, bestie, one by one:

app_data

a pointer to arbitrary application specific data. no thoughts, just vibes, it's yours πŸ’…

asn1_ex_new

a "new" function whose whole job is constructing a fresh ASN1_VALUE object. the newly constructed value should be stored in *pval. the it parameter is a pointer to the ASN1_ITEM template object created via the IMPLEMENT_EXTERN_ASN1() macro.

returns a positive value on success or 0 on error. slay ✨

asn1_ex_free

a "free" function that frees the ASN1_VALUE passed in *pval, which was previously allocated via a "new" function. the it parameter is a pointer to the ASN1_ITEM template object created via the IMPLEMENT_EXTERN_ASN1() macro.

asn1_ex_clear

a "clear" function that clears any data in the ASN1_VALUE passed in *pval and makes it suitable for reuse. the it parameter is a pointer to the ASN1_ITEM template object created via the IMPLEMENT_EXTERN_ASN1() macro.

asn1_ex_d2i

a "d2i" function that converts DER data with the tag tag and class class into an ASN1_VALUE. the details are highkey important so buckle up πŸ¦‹:

  • if *pval is non-NULL then the ASN_VALUE it points to should be reused. otherwise a new ASN1_VALUE should be allocated and stored in *pval.
  • *in points to the DER data to be decoded and len is the length of that data.
  • after decoding, *in should be updated to point at the next byte after the decoded data.
  • if the ASN1_VALUE is considered optional in this context then opt will be nonzero. otherwise it will be zero.
  • the it parameter is a pointer to the ASN1_ITEM template object created via the IMPLEMENT_EXTERN_ASN1() macro.
  • a pointer to the current ASN1_TLC context (which may be required for other ASN1 function calls) is passed in the ctx parameter.

the asn1_ex_d2i entry may be NULL if asn1_ex_d2i_ex has been specified instead.

returns <= 0 on error or a positive value on success. straightforward, iconic, no notes.

asn1_ex_i2d

an "i2d" function that converts an ASN1_VALUE into DER encoding. here's how the entry conditions go:

  • on entry, *pval will contain the ASN1_VALUE to be encoded.
  • if default tagging is to be used then tag will be -1 on entry. otherwise, if implicit tagging should be used, then tag and aclass will be the tag and associated class.

and for the writing part, pay attention bestie 😭:

  • if out is not NULL then this function should write the DER encoded data to the buffer in *out, and then increment *out to point to immediately after the data just written.
  • if out is NULL then no data should be written but the length calculated and returned as if it were.

the asn1_ex_i2d entry may be NULL if asn1_ex_i2d_ex has been specified instead.

the return value should be negative if a fatal error occurred, or 0 if a non-fatal error occurred. otherwise it should return the length of the encoded data. periodt πŸ’€

asn1_ex_print

a "print" function. the cast, one by one:

  • out is the BIO to print the output to.
  • *pval is the ASN1_VALUE to be printed.
  • indent is the number of spaces of indenting to be printed before any data is printed.
  • fname is currently unused and is always "".
  • pctx is a pointer to the ASN1_PCTX for the print operation.

returns 0 on error or a positive value on success. and here's the fun bit πŸŽ€ β€” if the return value is 2 then an additional newline will be printed after the data printed by this function. extra spacing, extra main character energy.

asn1_ex_new_ex

this is the same as asn1_ex_new except that it's additionally passed the OSSL_LIB_CTX to be used in libctx, and any property query string to be used for algorithm fetching in the propq parameter. see "ALGORITHM FETCHING" in crypto(7) for further details. and the rule: if asn1_ex_new_ex is non NULL, then it will always be called in preference to asn1_ex_new. it's giving "newer sibling always gets the aux" πŸ”₯

asn1_ex_d2i_ex

this is the same as asn1_ex_d2i except that it's additionally passed the OSSL_LIB_CTX to be used in libctx, and any property query string to be used for algorithm fetching in the propq parameter. see "ALGORITHM FETCHING" in crypto(7) for further details. and same deal β€” if asn1_ex_d2i_ex is non NULL, then it will always be called in preference to asn1_ex_d2i ✨


⭐ RETURN VALUES ⭐

return values for the various callbacks are as described above. iykyk πŸ’œ


🧚 SEE ALSO 🧚

ASN1_item_new_ex(3)


πŸ‘‘ HISTORY πŸ‘‘

the asn1_ex_new_ex and asn1_ex_d2i_ex callbacks were added in OpenSSL 3.0. glow-up era 🌸


Copyright 2021 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>.


okay that's the whole page, bestie, you're officially an external ASN.1 function girlie now πŸ«ΆπŸ’– this was ASN1_EXTERN_FUNCS(3ossl) from 3.5.0, dated 2026-09-25 β€” go forth and implement your externs, no cap ⭐

πŸ“¦ where this page comes from