调用openssl::i2d_X509后,释放输出缓冲区的正确方法是什么?

9
我希望将X509结构编码为DER字节。根据openssl(版本> 0.9.7)手册中的示例代码(i2d_X509函数),如果我需要让i2d_X509自行分配内存,则需要执行以下操作:
int len;
unsigned char *buf;

buf = NULL;

len = i2d_X509(x, &buf);

if (len < 0)
    /* error */

然而,从文档中并不完全清楚(但我认为需要调用OPENSSL_free),在完成对buf的操作后,释放内存的正确方式是什么?
正确的方法是调用OPENSSL_free来释放buf

你的假设看起来对我来说是正确的。 - Jabberwocky
@MichaelWalz,希望如此。但是这种行为没有明确定义,例如,即使发生错误,可能仍需要释放buf。 - tysonite
1个回答

5

简短回答: 必须使用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)用于处理原始问题中的一种情况,即当bufNULL时。因此,在内部,openssl使用OPENSSL_malloc函数为buf分配内存,这意味着必须使用OPENSSL_free函数释放内存。

注意:我查看了当前可在GH上找到的openssl源代码 (链接)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接