调用 openssl::i2d_X509 后释放输出缓冲区的正确方法是什么?
What is the correct way to free output buffer after call to openssl::i2d_X509?
我想将 X509 结构编码为 DER 字节。按照 openssl(版本 > 0.9.7)man page 中的源代码示例,我需要做的(如果我 i2d_X509
自己分配内存):
int len;
unsigned char *buf;
buf = NULL;
len = i2d_X509(x, &buf);
if (len < 0)
/* error */
但是,从文档中还不完全清楚(但我认为需要调用 OPENSSL_free
)在完成 buf
后释放内存的正确方法是什么。
释放buf
的正确方法是什么?
简答:必须使用OPENSSL_free
才能释放buf
。
长答案:
IMPLEMENT_ASN1_FUNCTIONS
宏扩展为 i2d_X509
函数的定义。下面的示例演示了将以下源代码放入 source.c
:
#include <openssl/asn1t.h>
IMPLEMENT_ASN1_FUNCTIONS(X509)
执行 gcc -E source.c
宏后扩展为:
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))); }
兴趣点是 i2d_X509
的定义,反过来该函数调用 ASN1_item_i2d
。根据 openssl 的源代码,ASN1_item_i2d
是 tasn_enc.c
文件中定义的函数:
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);
}
分支if (out && !*out)
用于原始问题中描述的情况(buf
是NULL
)。因此,在内部,openssl 使用 OPENSSL_malloc
为 buf
分配内存,因此必须使用 OPENSSL_free
来释放内存。
注意: 我查看了目前在GH上可用的openssl的源代码。
我想将 X509 结构编码为 DER 字节。按照 openssl(版本 > 0.9.7)man page 中的源代码示例,我需要做的(如果我 i2d_X509
自己分配内存):
int len;
unsigned char *buf;
buf = NULL;
len = i2d_X509(x, &buf);
if (len < 0)
/* error */
但是,从文档中还不完全清楚(但我认为需要调用 OPENSSL_free
)在完成 buf
后释放内存的正确方法是什么。
释放buf
的正确方法是什么?
简答:必须使用OPENSSL_free
才能释放buf
。
长答案:
IMPLEMENT_ASN1_FUNCTIONS
宏扩展为 i2d_X509
函数的定义。下面的示例演示了将以下源代码放入 source.c
:
#include <openssl/asn1t.h>
IMPLEMENT_ASN1_FUNCTIONS(X509)
执行 gcc -E source.c
宏后扩展为:
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))); }
兴趣点是 i2d_X509
的定义,反过来该函数调用 ASN1_item_i2d
。根据 openssl 的源代码,ASN1_item_i2d
是 tasn_enc.c
文件中定义的函数:
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);
}
分支if (out && !*out)
用于原始问题中描述的情况(buf
是NULL
)。因此,在内部,openssl 使用 OPENSSL_malloc
为 buf
分配内存,因此必须使用 OPENSSL_free
来释放内存。
注意: 我查看了目前在GH上可用的openssl的源代码。