ASN1_EXTERN_FUNCS(3SSL)
π ASN1_EXTERN_FUNCS β the OpenSSL manual page, bestie edition
okay so this is ASN1_EXTERN_FUNCS(3SSL), straight out of the OpenSSL manual, and we're gonna make it make sense. sit down, grab a strawberry, we're doing ASN.1 external function support πΈ
β¨ 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 β literally all of these are about ASN.1 external function support. that's the whole vibe. π¦
π 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)
no cap, that's a whole lot of function pointers and i'm obsessed with every single one of them π₯
π DESCRIPTION π
so normally, ASN.1 data structure templates get defined in OpenSSL using a parade of macros like ASN1_SEQUENCE(), ASN1_SEQUENCE_END() and friends. cute, right? but plot twist: you can also define templates based entirely on external functions. those external functions get called whenever OpenSSL needs to do stuff like making a fresh ASN1_VALUE, or turning an ASN1_VALUE to/from DER encoding. main character behaviour, honestly. β¨
the IMPLEMENT_EXTERN_ASN1() macro is how you build one of these externally defined structures. here's the tea on its parameters:
- the name of the structure goes in the
snameparameter - the tag for the structure goes in the
tagparameter (typicallyV_ASN1_SEQUENCE, iykyk) - and a pointer to an
ASN1_EXTERN_FUNCSstructure goes in thefptrsparameter
then the ASN1_EXTERN_FUNCS structure itself has these entries. buckle up: π
the struct fields, one by one
app_dataβ just a pointer to whatever arbitrary application specific data you want. it's giving "miscellaneous pocket."asn1_ex_newβ the "new" function, and its whole job is constructing a brand newASN1_VALUEobject. the freshly built value should land in*pval. theitparameter is a pointer to theASN1_ITEMtemplate object, the one created via thatIMPLEMENT_EXTERN_ASN1()macro.
returns a positive value on success, or 0 on error. no in-between, we don't do ambiguity here π
asn1_ex_freeβ the "free" function. it frees theASN1_VALUEpassed in*pval, the one that was previously allocated via a "new" function. theitparameter is a pointer to theASN1_ITEMtemplate object created via theIMPLEMENT_EXTERN_ASN1()macro.asn1_ex_clearβ the "clear" function. it clears any data in theASN1_VALUEpassed in*pvaland makes it suitable for reuse. (recycling era β»οΈ) theitparameter is a pointer to theASN1_ITEMtemplate object created via theIMPLEMENT_EXTERN_ASN1()macro.asn1_ex_d2iβ the "d2i" function, responsible for converting DER data with the tagtagand classclassinto anASN1_VALUE. details, because details matter:- if
*pvalis non-NULL, then theASN_VALUEit points to should be reused. otherwise a newASN1_VALUEshould be allocated and stored in*pval. *inpoints to the DER data to be decoded, andlenis the length of that data.- after decoding,
*inshould be updated to point at the next byte after the decoded data. - if the
ASN1_VALUEis considered optional in this context, thenoptwill be nonzero. otherwise it will be zero. - the
itparameter is a pointer to theASN1_ITEMtemplate object created via theIMPLEMENT_EXTERN_ASN1()macro. - a pointer to the current
ASN1_TLCcontext (which may be required for other ASN1 function calls) is passed in thectxparameter.
- if
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.
asn1_ex_i2dβ the "i2d" function, responsible for converting anASN1_VALUEinto DER encoding. on entry,*pvalwill contain theASN1_VALUEto be encoded.- if default tagging is to be used, then
tagwill be -1 on entry. - otherwise, if implicit tagging should be used, then
tagandaclasswill be the tag and associated class. - if
outis notNULL, this function should write the DER encoded data to the buffer in*out, and then increment*outto point to immediately after the data just written. - if
outisNULL, then no data should be written, but the length should still be calculated and returned as if it had been.
- if default tagging is to be used, then
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. (three different outcomes, pick wisely π)
asn1_ex_printβ the "print" function.outis theBIOto print the output to.*pvalis theASN1_VALUEto be printed.indentis the number of spaces of indenting to be printed before any data is printed.fnameis currently unused and is always"".pctxis a pointer to theASN1_PCTXfor the print operation.
returns 0 on error or a positive value on success. and here's the lil easter egg: if the return value is 2, then an additional newline will be printed after the data printed by this function. cute, right? π
asn1_ex_new_exβ same asasn1_ex_new, except it's additionally passed theOSSL_LIB_CTXto be used inlibctx, and any property query string to be used for algorithm fetching in thepropqparameter. for further details, see "ALGORITHM FETCHING" incrypto(7). and listen: ifasn1_ex_new_exis nonNULL, then it will always be called in preference toasn1_ex_new. it's the favourite child, periodt. πasn1_ex_d2i_exβ same asasn1_ex_d2i, except it's additionally passed theOSSL_LIB_CTXto be used inlibctx, and any property query string to be used for algorithm fetching in thepropqparameter. for further details, see "ALGORITHM FETCHING" incrypto(7). and same energy as above: ifasn1_ex_d2i_exis nonNULL, then it will always be called in preference toasn1_ex_d2i. π
π«Ά RETURN VALUES π«Ά
the return values for the various callbacks are exactly as described above. that's it, that's the section β go scroll back up, bestie, it's all up there π
π¦ SEE ALSO π¦
β HISTORY β
the asn1_ex_new_ex and asn1_ex_d2i_ex callbacks were added in OpenSSL 3.0. so if you're on something older... it's not giving. π
π COPYRIGHT π
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>.
and that's the whole page, bestie!! πβ¨ this was ASN1_EXTERN_FUNCS(3SSL) from the OpenSSL manual β version 4.0.3, dated 2026-09-29. slay responsibly, and remember: when asn1_ex_new_ex is non NULL it always wins. no cap. πππ¦
π¦ where this page comes from
- ubuntu stonking: libssl-doc 4.0.3-1ubuntu1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms