2014-04-30 119 views
5

我不是OpenSSL專家,但我一直在試圖編寫一些代碼來處理連接到SSL安全服務器的客戶端的OCSP裝訂。我對OCSP的理解是,它用於證明所提交的證書沒有被撤銷,這意味着我不需要處理管理髮行人發佈的CRL。爲什麼在驗證回調後調用OCSP裝訂回調?

我使用SSL_CTX_set_verify來設置處理證書驗證的回調函數(好吧,處理OpenSSL自己的內部驗證過程的異常我假設,但無法找到證明這個內部進程不檢查證書撤銷狀態的肯定證據),目前我的代碼使用這個機會來檢查發行人是否可信(或者如果不是,那麼發行人的發行人是可信的,依此類推,直到鏈是可信的或被拒絕的),以及諸如證書沒有過期。 (這也可能已經被檢查過,但這對我的問題並不重要)。

我修改了代碼,添加

SSL_set_tlsext_status_type(<the ssl object>, TLSEXT_STATUSTYPE_ocsp); 
SSL_CTX_set_tlsext_status_cb(<the context>, ssl_cb_ocsp_verify); 

,然後我可以得到響應,並檢查它在處理程序。到現在爲止還挺好!

但奇怪的是,我得到了OCSP回調我得到SSL_CTX_set_verify處理程序。對於我的(當然天真)的想法,這意味着我有兩個選擇:

1)檢查驗證回調中的撤銷狀態,使用CRL或者做我自己的OCSP請求。如果我這樣做,在OCSP回調中做任何事情都沒有意義,因爲我已經確定了證書的撤銷狀態 2)不要在驗證回調中檢查撤銷狀態,並且希望瘋狂地認爲OCSP處理程序叫做。

我確實注意到,如果來自服務器的響應不包含已裝訂的OCSP消息,則OCSP處理程序在之前被調用。所以有一種可能性是,我最初在'no_ocsp'的某個地方設置了一些標誌,然後如果我在沒有附加消息的情況下獲得OCSP回調,將其設置爲1.然後在驗證處理程序中,我可以檢查此操作以確定OCSP處理程序將在稍後調用。這看起來有點像一輛汽車,隨着任何人的接近自我解鎖,然後如果接近的人放錯了鑰匙,它就會自我鎖定 - 換句話說,它肯定不能成爲安全的「正確」方式?!

因此,我必須對如何使用OCSP,OpenSSL或兩者有一些基本的誤解!我究竟做錯了什麼?

(我見過的解釋如何得到的OCSP訂書針的消息,但我的問題涉及到如何真正以一種合理的方式,用它給回調的順序類似的問題要明確:我可以在沒有任何問題的情況下獲得OCSP_RESPONSE)

+0

「......處理例外的OpenSSL自己的內部覈查過程中,我認爲」檢查CRL。如果需要的話,你必須這樣做。 – jww

+0

啊哈,謝謝你的提示!我發現了一篇白皮書「你一直想用openssl知道證書驗證的一切(但不敢問)」,它提供了一些額外的信息,但不幸的是沒有OCSP(除了一個簡短的提及) – trime

+0

在您信任服務器告訴您的信息之前(例如_ OCSP裝訂),您首先需要信任該服務器,因此OpenSSL可能會驗證服務器的證書_first_,確保它是有效且可信的證書_at所有_。然後,假設證書看起來是有效的,那麼您需要查看它是否已被撤銷 - 這是您處理/處理已裝訂的OCSP響應的時間。 – Castaglia

回答

0

第三種選擇是請求CRL點和OCSP回覆,然後以正確的順序驗證自己。

您使用OCSP_basic_verify驗證回調中的OCSP stapled回覆。也知道,OpenSSL的前1.02不*不*執行主機名匹配 - 然後,一旦連接建立,您可以通過

X509_STORE_CTX* ctx = ... 

// fill up ctx, if not yet initialized 
ctx->chain = chain; 
ctx->get_crl = [](X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x) -> int 
{ .. your method to download CRL .. } 
// disable additional CRL lookup by the library 
ctx->lookup_crls = [] (X509_STORE_CTX *ctx, X509_NAME *nm) ->STACK_OF(X509_CRL) * { return nullptr; }; 
// other possible options are: X509_V_FLAG_EXTENDED_CRL_SUPPORT, X509_V_FLAG_CRL_CHECK_ALL, X509_V_FLAG_USE_DELTAS 
ctx->param->flags = X509_V_FLAG_CRL_CHECK; 

// this will evaluate how well the CRL fits the leaf certificate you want to validate 
ctx->check_revocation(ctx); 

// this validates the CRL itself, if it is signed and stuff 
// 0 - bad 
// 1 - okay 
int ok = ctx->check_crl(ctx, m_crl); 

// This gives actual revocation result 
// 0 - bad (ctx->error = X509_V_ERR_CERT_REVOKED or something else) 
// 1 - okay 
// 2 - CRL_REASON_REMOVE_FROM_CRL 
int result = ctx->cert_crl(ctx, m_crl, leafCertificate);