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