OpenSSL API: asn1_par.c原始碼分析
阿新 • • 發佈:2020-05-02
序
openssl有關asn1編解碼的函式都定義在crypto/asn1/asn1_par.c
下,這些函式直接在官方文件裡是找不到的,也就是說openssl其實沒有直接暴露asn1編解碼的介面,而是在這之上又封裝了一層證書格式,比如X509
。
但是由於我們要做的是asn1的解碼器,而不是針對證書格式的解碼,所以無法直接呼叫openssl暴露的介面,只能通過學習原始碼來編寫API供後面的軟體使用。
概覽
原型
一共有五個函式
static int asn1_print_info(BIO *bp,int tag,int xclass,int constructed,int indent) int ASN1_parse(BIO *bp,const unsigned char *pp,long len,int indent) int ASN1_parse_dump(BIO *bp,int indent,int dump) static int asn1_parse2(BIO *bp,const unsigned char **pp,long length,int offset,int depth,int dump) const char *ASN1_tag2str(int tag)
功能
ASN1_parse()
,ASN1_parse_dump()
openssl asn1parse
命令直接呼叫的函式,其實內部都呼叫了asn1_parse2()
,唯一的區別就是輸出格式的不同,詳情看後面的分析asn1_parse2()
真正進行解碼的函式。本函式用於將pp
和len
指明的DER編碼值寫在BIO中,其中indent
和dump
用於設定列印的格式。indent用來設定打印出來當列之間空格個數,ident
越小,列印內容越緊湊。dump
表明當asn1單元為BIT STRING
或OCTET STRING
時,列印內容的位元組數ASN1_tag2str()
根據tag的值返回對應型別的名稱字串asn1_print_info()
按格式列印解碼出的asn1資訊
ASN1_parse/ASN1_parse_dump
不多說
ASN1_tag2str
將tag值和型別名稱對應起來
asn1_print_info
輸出傳入的結構是結構化的還是原始的,以及對應的tag
asn1_parse2
重頭戲,首先要明白這是個遞迴函式
引數
BIO *bp
解析過程中所有的結果都會寫入這個BIO中const unsigned char *pp
其中包含需要解析的二進位制資料long length
,pp
中需要解析二進位制資料的長度int offset
偏移量,初始值0,在遞迴過程中會被修改int depth
int indent
用來設定打印出來當列之間空格個數,ident
越小,列印內容越緊湊int dump
表明當asn1單元為BIT STRING
或OCTET STRING
時,列印內容的位元組數
整體結構
asn1_parse2(){
while (length > 0) {
if(xxx){
...
goto end;
}
if(xxx){
asn1_parse2()
}
length -= len
}
end:
free();
return ret;
}
詳細分析
接下來一步一步分析
超過最大遞迴層數時退出
ASN1_get_object
定義在asn1_lib.c
中,會在其中修改傳入的指標位置,hl
計算出頭部長度,然後length
從中減掉hl
(long)offset + (long)(op - *pp)
算出偏移
依次輸出層數、頭部長度、長度,以及呼叫asn1_print_info
如果當前解析的結構是結構化的,那麼遞迴呼叫asn1_parse2,對內層進行解析