asn1编码格式的解析过程
本文以x509的解析为例说明asn1的编码格式的解析逻辑。x509证书的解析实际上是asn1格式的解析,这里着重说的是asn1的ber编码的解析,总的来讲,asn1格式的解析过程有三个重要的元素,一个是asn1数据本身,一个是openssl的内部数据结构,比如X509_st,还有一个指导asn1数据往内部数据结构填充的结构体,这个过程实际上就是d2i,而反向的过程就是i2d,asn1作为抽象语法标记语言,ber其实只是其一种编码实现,不管什么实现都要体现“抽象数据结构”本身,这种数据结构其实很显然,标记了类型,标记了数据的长度以及数据本身等,每一种标记都是自解释的,因此最完美的解决方案就是将openssl的内部数据结构也规整为前面所说的这种“抽象数据结构”,也即是说,将内部数据结构作为asn1的另一种编码格式,和ber并列的编码格式,这样就很好理解d2i的过程了,同样i2d是一种和d2i并列的转换,这么理解的话,ber编码和内部编码实质上是同一种意思的两种不同表述,以x509为例,如果现在有一个x509的der格式的数字证书,有一个openssl的x509数据结构,以下的两个数据结构就是这个d2i过程的指导结构:
ASN1_ITEM_st表述一个“项”,这个“项”是一种复合结构,templates是一个ASN1_ITEM_st容器,该容器可以容纳一个ASN1_ITEM_st也可以容纳多个ASN1_ITEM_st,多个ASN1_ITEM_st同样以templates为更低一级的容器,实质上在我们的例子中,x509_cinf结构体就是一个ASN1_ITEM_st,其中包含一系列的ASN1_TEMPLATE,这个一会会谈到:
struct ASN1_ITEM_st {
char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */
long utype; /* underlying type */
const ASN1_TEMPLATE *templates; //用于itype是SEQUENCE的情况,而一个templates又要包含一个ASN1_ITEM,注释0
long tcount; /* Number of templates if SEQUENCE or CHOICE */
const void *funcs; /* functions that handle this type */
long size; //被描述的内部结构体的大小
};
ASN1_TEMPLATE是ASN1_ITEM的内容容器,真正的内容还是ASN1_ITEM,由于ASN1是一个大的嵌套体,所以每个ASN1_ITEM还可以包含别的ASN1_ITEM,这些ITEM通过TEMPLATE进行汇总,也就是说一个TEMPLATE可以容纳很多存在于TEMPLATE中的ITEM:
struct ASN1_TEMPLATE_st {
unsigned long flags; //指示一些特殊用途,比如变长结构或者是可选信息等
long tag; //asn.1的tag
unsigned long offset; //该TEMPLATE在被描述结构体的偏移
ASN1_ITEM_EXP *item; //每个TEMPLATE由一个ASN1_ITEM描述,此字段指向该ITEM
};
以下几个#define是几个帮助宏,学过