在openssl crypto库中,有很多形似i2d_xxx和d2i_xxx的函数,而且用source insight这样的代码浏览工具是没法找到其定义的,在我刚刚接触openssl的时候,着实郁闷了一阵子,就是找不到定义。后来才发现了这一系列函数的来源。原来他们是通过宏定义的方式来实现的。
在asn1.h中,有一系列的宏定义,其中DECLARE_ASN1_ENCODE_FUNCTIONS就是用于d2i和i2d的原型。
#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) / type *d2i_##name(type **a, unsigned char **in, long len); / int i2d_##name(type *a, unsigned char **out); / DECLARE_ASN1_ITEM(itname)
对于此宏,如果传入参数为x509,那么扩展以后将变为 X509 *d2i_x509(type **a, unsigned char **in, long len); int i2d_509(type *a, unsigned char **out); DECLARE_ASN1_ITEM(x509)
这就是d2i和i2d的声明,那么函数定义呢?类似的在asn1t.h中,有这样的宏定义。
#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) / stname *d2i_##fname(stname **a, 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));/ }
这个宏中,同样的可以扩展为d2i_x509和i2d_x509的实现。
x509 *d2i_x509(x509 **a, unsigned char **in, long len)
{
return (x509 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(x509));
}
int i2d_x509(x509 *a, unsigned char **out)
{
return ASN1_iem_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(x509));
}
通过上面的扩展,发现最终所有类似的函数都是通过ASN1_item_d2i和ASN1_item_i2d 来实现的。ASN1_VALUE的声明在这里
/* This is just an opaque pointer */ typedef struct ASN1_VALUE_st ASN1_VALUE;
从注释我们可以知道他并没有实际的结构体定义。
/* Macro to include ASN1_ITEM pointer from base type */ #define ASN1_ITEM_ref(iptr) (&(iptr##_it))
#define ASN1_ITEM_rptr(ref) (&(ref##_it))
#define DECLARE_ASN1_ITEM(name) / OPENSSL_EXTERN const ASN1_ITEM name##_it;
下次再来深入看看ASN1_item_d2i和ASN1_item_i2d 这2个函数的具体实现。。