i2d_ASN1_OBJECT 问题
i2d_ASN1_OBJECT issue
我正在尝试使用 openssl 库将 ASN1_OBJECT 编码为 DER。
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 已预填充 STACK OF X509_ALGORs。我的 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)
您参考的手册页提到
If *ppout is NULL memory will be allocated for a buffer and the
encoded data written to it.
但是,您使用的函数 i2d_ASN1_OBJECT()
并非如此。查看 the source code of that function in a_object.c, no allocation anywhere. The segfault happens 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
函数是通过此模板机制定义的(其中大多数是),该函数就会为您进行分配。否则,你将不得不自己做。
我正在尝试使用 openssl 库将 ASN1_OBJECT 编码为 DER。 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 已预填充 STACK OF X509_ALGORs。我的 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)
您参考的手册页提到
If *ppout is NULL memory will be allocated for a buffer and the encoded data written to it.
但是,您使用的函数 i2d_ASN1_OBJECT()
并非如此。查看 the source code of that function in a_object.c, no allocation anywhere. The segfault happens 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
函数是通过此模板机制定义的(其中大多数是),该函数就会为您进行分配。否则,你将不得不自己做。