1

我正在尝试使用 openssl lib 将 ASN1_OBJECT 编码为 DER。有一个函数 i2d_ASN1_OBJECT 记录在https://www.openssl.org/docs/man1.1.0/crypto/i2d_X509.html中,我还有一个可以工作的示例代码(对于另一种对象类型):

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 )

4

1 回答 1

0

您提到的手册页

如果 *ppout 为 NULL,将为缓冲区分配内存并将编码数据写入其中。

但是,这不适用于i2d_ASN1_OBJECT()您使用的功能。在 a_object.c 中查看该函数的源代码,任何地方都没有分配。段错误发生在这里,在 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(),如果您尝试将它与NULLout 指针一起使用,它实际上也会崩溃。

那么为什么文档与您的经验相矛盾,为什么它适用于您的其他代码片段?文档不准确,但大多数其他i2d_XYZ()功能都是通过(复杂的)模板方案由functionasn1_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);
}

这里的一些模板化函数(间接)调用它:

# 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您使用的功能是通过此模板机制定义的,(其中大多数是)该功能将为您进行分配。否则,您将不得不自己做。

于 2018-08-11T05:59:03.733 回答