openssl 程式碼分析(4) ASN1_item_ex_d2i
ASN1_item_ex_d2i的引數
pval: 由caller傳入,用於接收返回值。
in: 由caller傳入,是輸入字串,待decode的buffer
len:待decode buffer的長度
it: X509_it
tag: –1
aclass: 0
opt: 0
ctx: caller的local variable,已經clear,其valid field為0.
展開
ASN1_SEQUENCE_ref(X509, x509_cb, CRYPTO_LOCK_X509) = {
ASN1_SIMPLE(X509, cert_info, X509_CINF),
ASN1_SIMPLE(X509, sig_alg, X509_ALGOR),
ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_ref(X509, X509)
如下:
const static ASN1_AUX X509_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(X509, references), CRYPTO_LOCK_X509, x509_cb, 0};
const static ASN1_TEMPLATE X509_seq_tt[] ={
{(0),(0),offsetof(X509,cert_info),”cert_info”, &X509_CINF_it},
{(0),(0),offsetof(X509,sig_alg),”sig_alg”, &X509_ALGOR_it},
{(0),(0),offsetof(X509,signature),”signature”, &ASN1_BIT_STRING_it},
}
static const ASN1_ITEM local_it = {
ASN1_ITYPE_SEQUENCE,
V_ASN1_SEQUENCE,
X509_seq_tt,
sizeof(X509_seq_tt) / sizeof(ASN1_TEMPLATE),
X509_aux,
sizeof(X509),
X509
}
X509_CINF_it,X509_ALGOR_it和ASN1_BIT_STRING_it則又可分別展開為下一級的ASN1_TEMPLATE。
在函式ASN1_item_ex_d2i中,在一系列的區域性變數初始化之後,是一個大的switch語句,根據itype分別做處理,對於X509,通過前面X509_it的定義,我麼知道他是ASN1_ITYPE_SEQUENCE型別,所以直接跳到對應的處理邏輯line292.
在function,ASN1_utem_ex_d2i中,針對SEQUENCE型別的資料,有一個最重要的程式碼段來處理。
在line326處,有一個for迴圈,迴圈的是X509_it的template,也就是”Cert_info”, “sig_alg”和“signature”,也就是說會按這個順序是解析輸入的buffer。像X509_CINF_it又定義了類似的template集合,那麼在處理”cert_info”的時候,又會遞迴的去處理X509_CINF_it的每一個template,直到完成為止。每一個template的處理完成,都會呼叫sk_push將結果儲存到目標中,最終形成了X509的輸出。
至此,d2i_x509的大致流程就是這樣了,當然裡面的細節還很多,整體工作原理很簡單如下:
對於DER format的資料流,針對X509定義了一系列的template,template可以巢狀,最頂層的template就是像ASN1_INTEGER這樣的型別,也就是說ASN1編碼格式最終都是由ASN1_INTEGER這樣的elements組成的。正因為如此,所以針對X509的每一個部分,都有對應的d2i_x509_xx函式可以呼叫來進行decode。具體可以查閱utils/libeay.num裡面的函式export定義。
要了解ASN1的編碼格式細節,可以參考這裡。瞭解了ASN1,再來細細瞭解ASN1 decode的細節應該相對容易一些。所以我想d2i的意思應該是DER to INFO,只是我猜測,沒找到官方說法。