On 2009-06-02 11:17 PDT, Wan-Teh Chang wrote:
> This message is long.  Please bear with me.

A mere 73 lines.  :)

> On 2008-12-18, Dan Kegel reported in this thread that we can't call
> SSL_PeerCertificate after the bad-certificate callback function returns
> because the peer certificate has been destroyed:
> 
> http://www.nabble.com/A-tip-for-novice-users-of-SSL_BadCertHook-and-SSL_PeerCertificate-td21080085.html

Well, of course, you can call it at any time that you have an SSL socket.
The questions of interest are (or may be):
- when can you call it and expect to get a non-NULL result, and
- when can you expect that the entire cert chain received from the TLS peer
will still be present as "temporary certificates", with the result that an
attempt to validate the peerCert can possibly succeed.

> However, recently while working with another Chromium developer, I
> noticed that he is calling SSL_PeerCertificate after the handshake is
> completed.

These findings are not necessarily mutually exclusive or contradictory.
I think Dan was assuming that the bad-cert handler would not "override"
the error.

The "auth cert" callback and the "bad cert" handler callback are both called
from within the function ssl3_HandleCertificate, which handles the SSL/TLS
Certificate message received from the peer system (either client or server).
If there is an error reported by the "authCert" callback, and there is no
bad cert handler registered, or the registered bad cert handler does not
override the error, then Dan's claim is correct.

At the conclusion of the processing of the received SSL/TLS Certificate
message, by the time that ssl3_HandleCertificate returns, if the conclusion
is that the cert is bad, then at label "loser", the received cert and its
associated chain will be "destroyed" (that is, the reference count will be
decremented), and the associated pointers in the socket structure will be
NULLed.

If the conclusion is that the cert is good, then the "peerCert" pointer
will remain valid, and the temporary certs received from the peer will
remain, until either
   a) the socket is closed, or
   b) a subsequent handshake occurs on the socket.


> So I inspected the NSS and PSM source code to understand why. Here are my
> findings from inspecting the PSM and NSS source code.
> 
> 1. SSL_PeerCertificate can be called during the handshake
> completion callback, because PSM does that:

> 2. In the NSS source code, I didn't find any evidence
> that the peer certificate is destroyed as soon as the
> handshake is completed. 

NSS did so, long ago, but that was changed long ago in response to an RFE
from PSM.  I do not recall specifically where or when that change occurred.
It may have been back during NSS 2.x.

> On the contrary, I only found
> that we destroy the peer certificate when we close the
> SSL socket.  

Or we start a new handshake.

> Specifically, I found that peerCert and peerCertChain are destroyed in
> the ssl_DestroySecurityInfo and ssl3_DestroySSL3Info calls in
> ssl_DestroySocketContents which is called by ssl_FreeSocket.

The peer cert chain is destroyed by ssl3_CleanupPeerCerts, which is called
in numerous places.  See
http://mxr.mozilla.org/security/ident?i=ssl3_CleanupPeerCerts

> So I believe that the Note that I added to our documentation
> is wrong, or at least confusing:
> 
>   To obtain the certificate that was rejected by the certificate
>   authentication callback, the bad-certificate callback function
>   calls SSL_PeerCertificate. Since it is called immediately
>   after the certificate authentication callback returns, the
>   bad-certificate callback function can obtain the error code
>   set by the certificate authentication callback by calling
>   PR_GetError immediately, as the first operation it performs.

The statements quoted above are certainly correct.

>   Note: once the bad-certificate callback function returns,
>   the peer certificate is destroyed, and SSL_PeerCertificate
>   will fail.
> 
> It seems that the peer certificate is destroyed only if the 
> bad-certificate callback function returns SECFailure.  If there is no
> certificate error or the bad-certificate callback ignores a certificate
> error (returning SECSuccess),

I would add here, ... and no other errors occur which are fatal to the
completion of the handshake ...

> it seems that we can call SSL_PeerCertificate all the way until the SSL
> socket is closed.

You can call it at any time.  Once a handshake has completed successfully,
it will return the peer cert until another handshake begins or the socket
is closed.

> Does anyone know exactly when we destroy the peer certificate and peer
> certificate chain?

Yes.

>
> Note: The way Chromium uses NSS to verify SSL server
> certificates has changed since Dan Kegel posted that message.
> Since certificate verification can block indefinitely while
> downloading CRLs or talking to OCSP responders, Chromium
> is verifying certificates on a thread pool (so it won't block the
> message loop of the main thread) after the handshake is completed.
> Chromium now has an auth-certificate callback that always
> returns SECSuccess, and is no longer using a bad-certificate
> callback.

That means that you always put the cert and its chain into the client's
cache, and cache the negotiated SSL session, where it will be restarted
by future attempts to connect to the same host/port.  This seems inadvisable.
-- 
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto

Reply via email to