我正在尝试使用openssl lib编码为ASN1_OBJECT。 https://www.openssl.org/docs/man1.1.0/crypto/i2d_X509.html中记录了一个函数i2d_ASN1_OBJECT,我也有一个示例代码可以工作(对于另一种对象类型):
unsigned char *smder = NULL;
int smderlen, r;
smderlen = i2d_X509_ALGORS(algs, &smder);
if (smderlen <= 0)
return 0;
其中的Algs是预填充的X509_ALGOR堆栈。我的ASN1_OBJECT代码:
unsigned char *ctder = NULL;
int ctderlen, r;
ASN1_OBJECT* obj = OBJ_txt2obj("1.2.3.4", 1);
ctderlen = i2d_ASN1_OBJECT(obj, &ctder); // SEGFAULT here
if (ctderlen <= 0)
return 0;
我在那里遇到段错误。
更新
那是一个错误,现已修复(请参阅:https://github.com/openssl/openssl/issues/6914)
答案 0 :(得分:0)
您引用的手册页
如果* ppout为NULL,则将为缓冲区分配内存,并且 写入的编码数据。
但是,对于您使用的功能i2d_ASN1_OBJECT()
,情况并非如此。检出the source code of that function in a_object.c,无处分配。段发生here, one level deeper in ASN1_put_object。
由于它不会为您分配内存,因此您必须自己提供一个缓冲区,如下所示:
unsigned char ctderarray[64];
unsigned char *ctder = ctderarray;
int ctderlen, r;
ASN1_OBJECT* obj = OBJ_txt2obj("1.2.3.4", 1);
ctderlen = i2d_ASN1_OBJECT(obj, &ctder);
if (ctderlen <= 0) {
return 0;
} else {
printf("ctderlen = %d\n", ctderlen);
}
,它将打印值5
。另一个不为您分配功能的函数示例为i2d_ASN1_BOOLEAN()
,如果您尝试将其与NULL
out指针一起使用,则确实会崩溃。
那么,文档为何与您的经验相抵触,为什么对其他代码段却有效?该文档并不准确,但是大多数其他i2d_XYZ()
函数是由the function asn1_item_flags_i2d()
通过(复杂的)模板方案以通用方式实现的。在那里,分配确实会为您完成:
/*
* Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
* points to a buffer to output the data to. The new i2d has one additional
* feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
* allocated and populated with the encoding.
*/
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)
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);
}
由某些模板化功能here(间接)调用:
# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \
stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
{ \
return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
} \
int i2d_##fname(stname *a, unsigned char **out) \
{ \
return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
}
只要您正在使用的i2d_XYZ
函数是通过此模板机制定义的(大多数都是),该函数就会为您分配资源。否则,您将必须自己做。