From 8dd1631f2aa8512be172e3d94a209d241baeb36d Mon Sep 17 00:00:00 2001 From: "wtc@chromium.org" Date: Sat, 19 Oct 2013 18:35:37 +0000 Subject: [PATCH] Do not allow the server certificate to change in a renegotiation. R=agl@chromium.org,rsleevi@chromium.org BUG=306959 TEST=none Review URL: https://codereview.chromium.org/27266002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229611 0039d316-1c4b-4281-b951-d872f2087c98 --- net/base/net_error_list.h | 3 +++ net/socket/nss_ssl_util.cc | 4 ++++ net/socket/ssl_client_socket_nss.cc | 13 +++++++++++++ 3 files changed, 20 insertions(+) diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index ec25dc4cf1a0..559c5a317cf2 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h @@ -300,6 +300,9 @@ NET_ERROR(WS_THROTTLE_QUEUE_TOO_LARGE, -154) // was rejected. NET_ERROR(TOO_MANY_SOCKET_STREAMS, -155) +// The SSL server certificate changed in a renegotiation. +NET_ERROR(SSL_SERVER_CERT_CHANGED, -156) + // Certificate error codes // // The values of certificate error codes must be consecutive. diff --git a/net/socket/nss_ssl_util.cc b/net/socket/nss_ssl_util.cc index ae037b17c1e9..7e3aee430c44 100644 --- a/net/socket/nss_ssl_util.cc +++ b/net/socket/nss_ssl_util.cc @@ -233,6 +233,10 @@ int MapNSSError(PRErrorCode err) { case SEC_ERROR_BAD_DER: case SEC_ERROR_EXTRA_INPUT: return ERR_SSL_BAD_PEER_PUBLIC_KEY; + // During renegotiation, the server presented a different certificate than + // was used earlier. + case SSL_ERROR_WRONG_CERTIFICATE: + return ERR_SSL_SERVER_CERT_CHANGED; default: { if (IS_SSL_ERROR(err)) { diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index f487abd4cc95..bfd0d0eddf6c 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -1287,6 +1287,19 @@ SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler( // Start with it. SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE); } + } else { + // Disallow the server certificate to change in a renegotiation. + CERTCertificate* old_cert = core->nss_handshake_state_.server_cert_chain[0]; + CERTCertificate* new_cert = SSL_PeerCertificate(socket); + if (new_cert->derCert.len != old_cert->derCert.len || + memcmp(new_cert->derCert.data, old_cert->derCert.data, + new_cert->derCert.len) != 0) { + // NSS doesn't have an error code that indicates the server certificate + // changed. Borrow SSL_ERROR_WRONG_CERTIFICATE (which NSS isn't using) + // for this purpose. + PORT_SetError(SSL_ERROR_WRONG_CERTIFICATE); + return SECFailure; + } } // Tell NSS to not verify the certificate. -- 2.11.4.GIT