Short answer : OPENSSL_free
should be used to free buf
.
Long answer : The macro IMPLEMENT_ASN1_FUNCTIONS
expands to define the function i2d_X509
. The example below shows that the following source code is placed in source.c
:
#include <openssl/asn1t.h> IMPLEMENT_ASN1_FUNCTIONS(X509)
After running gcc -E source.c
macro expands to:
X509 *d2i_X509(X509 **a, const unsigned char **in, long len) { return (X509 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, (&(X509_it))); } int i2d_X509(X509 *a, unsigned char **out) { return ASN1_item_i2d((ASN1_VALUE *)a, out, (&(X509_it))); } X509 *X509_new(void) { return (X509 *)ASN1_item_new((&(X509_it))); } void X509_free(X509 *a) { ASN1_item_free((ASN1_VALUE *)a, (&(X509_it))); }
The point of interest is the definition of i2d_X509
, which in turn calls ASN1_item_i2d
. According to the openssl source code, ASN1_item_i2d
is the function defined in the tasn_enc.c
file:
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it, int flags) { if (out && !*out) { unsigned char *p, *buf; int len; len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags); if (len <= 0) return len; buf = OPENSSL_malloc(len); if (buf == NULL) return -1; p = buf; ASN1_item_ex_i2d(&val, &p, it, -1, flags); *out = buf; return len; } return ASN1_item_ex_i2d(&val, out, it, -1, flags); }
The if (out && !*out)
branch is used in the case described in the original question ( buf
is NULL
). Thus, internalsoft openssl allocates memory for buf
using OPENSSL_malloc
, and as a result, OPENSSL_free
should be used to free memory.
Note. I was looking at the openssl source code currently available in GH.