Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the OCSP stapling callback called AFTER the verification callback?

Tags:

openssl

ocsp

I'm not an OpenSSL expert, but I've been trying to write some code to handle OCSP stapling for a client connecting to a SSL-secured server. My understanding of OCSP is that it is used to prove that the certificate being presented has not been revoked, which means that I don't need to deal with managing the CRLs published by the issuer.

I use SSL_CTX_set_verify to set a callback for handling verification of the certificates (well, handling exceptions to OpenSSL's own internal verification process. I assume, but cannot find positive proof that this internal process does not check the revocation status of the certificate), and currently my code uses this opportunity to check that the issuer is trusted (or if not, then the issuer's issuer is trusted, and so on until either the chain is trusted, or rejected), as well as other things such as the certificate is not expired. (This too may be already checked, but that's not really important for my question).

I modified my code, adding

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

and then I can get the response and check it in the handler. So far, so good!

But the weird thing is that I get the OCSP callback after I get the SSL_CTX_set_verify handler. To my (admittedly naive) thinking, this means I have two options:

1) Check the revocation status in the verification callback, either using the CRL, or doing my own OCSP request. If I do this, there's no point in doing anything in the OCSP callback, since I've already determined the revocation status of the certificate 2) Do not check the revocation status in the verification callback, and hope like crazy that the OCSP handler is called.

I did notice that the OCSP handler is called before the verification handler if the response from the server does not include a stapled OCSP message. So one possibility is that I set some flag somewhere 'no_ocsp' to 0 initially, and then if I get the OCSP callback with no message attached, set it to 1. Then in the verification handler I can check this to try and determine if the OCSP handler will be called later. This seems a bit like a car that unlocks itself as anyone approaches, and then if the person approaching puts the wrong key in, it locks itself - in other words, it surely cannot be the 'right' way to do security?!

So therefore, I must have some fundamental misunderstanding of how to use OCSP, OpenSSL, or both! What am I doing wrong?

(I've seen similar questions which explain how to get the OCSP-stapled message, but my question relates to how you actually use it in a sensible way, given the order of the callbacks. To be clear: I can get the OCSP_RESPONSE without any problems)

like image 581
trime Avatar asked Apr 30 '14 14:04

trime


1 Answers

Third option would be to request CRL points and OCSP reply and then validate yourself in the right order.

You validate OCSP stapled reply within callback, using OCSP_basic_verify. Then, once connection was established, you check CRL by

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);
like image 184
Evgeny Yashin Avatar answered Oct 21 '22 12:10

Evgeny Yashin