diff options
author | wez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-23 05:12:39 +0000 |
---|---|---|
committer | wez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-23 05:12:39 +0000 |
commit | b0ff3f8e755f87da1aedeaf051b88f53662f8652 (patch) | |
tree | 446118d1debf5c4b626a156f4be19db7e5dbbe05 /net/socket | |
parent | 5ef4e231a73a0a5910597c53f69592a11326ea54 (diff) | |
download | chromium_src-b0ff3f8e755f87da1aedeaf051b88f53662f8652.zip chromium_src-b0ff3f8e755f87da1aedeaf051b88f53662f8652.tar.gz chromium_src-b0ff3f8e755f87da1aedeaf051b88f53662f8652.tar.bz2 |
Expose SSL_ExportKeyingMaterial() in SSLClient/ServerSocket interfaces.
BUG=88130
TEST=
Review URL: http://codereview.chromium.org/7485015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93781 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket')
-rw-r--r-- | net/socket/nss_ssl_util.cc | 2 | ||||
-rw-r--r-- | net/socket/socket_test_util.cc | 8 | ||||
-rw-r--r-- | net/socket/socket_test_util.h | 4 | ||||
-rw-r--r-- | net/socket/ssl_client_socket.h | 12 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_mac.cc | 7 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_mac.h | 4 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 18 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.h | 4 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl.cc | 6 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl.h | 4 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_win.cc | 7 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_win.h | 4 | ||||
-rw-r--r-- | net/socket/ssl_server_socket.h | 14 | ||||
-rw-r--r-- | net/socket/ssl_server_socket_nss.cc | 18 | ||||
-rw-r--r-- | net/socket/ssl_server_socket_nss.h | 4 | ||||
-rw-r--r-- | net/socket/ssl_server_socket_unittest.cc | 56 |
16 files changed, 165 insertions, 7 deletions
diff --git a/net/socket/nss_ssl_util.cc b/net/socket/nss_ssl_util.cc index 2468168..16a1d8b 100644 --- a/net/socket/nss_ssl_util.cc +++ b/net/socket/nss_ssl_util.cc @@ -189,6 +189,8 @@ int MapNSSError(PRErrorCode err) { return ERR_SSL_UNSAFE_NEGOTIATION; case SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY: return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY; + case SSL_ERROR_HANDSHAKE_NOT_COMPLETED: + return ERR_SSL_HANDSHAKE_NOT_COMPLETED; default: { if (IS_SSL_ERROR(err)) { diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index faa3dea..ce64bdc 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc @@ -679,6 +679,14 @@ void MockClientSocket::GetSSLCertRequestInfo( net::SSLCertRequestInfo* cert_request_info) { } +int MockClientSocket::ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + SSLClientSocket::NextProtoStatus MockClientSocket::GetNextProto(std::string* proto) { proto->clear(); diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index fa9abd9..6b7cc5c 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h @@ -605,6 +605,10 @@ class MockClientSocket : public net::SSLClientSocket { virtual void GetSSLInfo(net::SSLInfo* ssl_info); virtual void GetSSLCertRequestInfo( net::SSLCertRequestInfo* cert_request_info); + virtual int ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen); virtual NextProtoStatus GetNextProto(std::string* proto); protected: diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h index 8dfd25d..ba7fefb 100644 --- a/net/socket/ssl_client_socket.h +++ b/net/socket/ssl_client_socket.h @@ -13,6 +13,10 @@ #include "net/base/net_errors.h" #include "net/socket/stream_socket.h" +namespace base { +class StringPiece; +} // namespace base + namespace net { class CertVerifier; @@ -110,6 +114,14 @@ class NET_API SSLClientSocket : public StreamSocket { virtual void GetSSLCertRequestInfo( SSLCertRequestInfo* cert_request_info) = 0; + // Exports data derived from the SSL master-secret (see RFC 5705). + // The call will fail with an error if the socket is not connected, or the + // SSL implementation does not support the operation. + virtual int ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen) = 0; + // Get the application level protocol that we negotiated with the server. // *proto is set to the resulting protocol (n.b. that the string may have // embedded NULs). diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc index dd5bdd9..de70ab0 100644 --- a/net/socket/ssl_client_socket_mac.cc +++ b/net/socket/ssl_client_socket_mac.cc @@ -783,6 +783,13 @@ void SSLClientSocketMac::GetSSLCertRequestInfo( << cert_request_info->client_certs.size() << " client certs..."; } +int SSLClientSocketMac::ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen) { + return ERR_NOT_IMPLEMENTED; +} + SSLClientSocket::NextProtoStatus SSLClientSocketMac::GetNextProto(std::string* proto) { proto->clear(); diff --git a/net/socket/ssl_client_socket_mac.h b/net/socket/ssl_client_socket_mac.h index e2830b3..2a3418e 100644 --- a/net/socket/ssl_client_socket_mac.h +++ b/net/socket/ssl_client_socket_mac.h @@ -43,6 +43,10 @@ class SSLClientSocketMac : public SSLClientSocket { // SSLClientSocket methods: virtual void GetSSLInfo(SSLInfo* ssl_info); virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); + virtual int ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen); virtual NextProtoStatus GetNextProto(std::string* proto); // StreamSocket methods: diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 0a28439..eddac5c 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -523,6 +523,24 @@ void SSLClientSocketNSS::GetSSLCertRequestInfo( LeaveFunction(cert_request_info->client_certs.size()); } +int SSLClientSocketNSS::ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen) { + if (!IsConnected()) + return ERR_SOCKET_NOT_CONNECTED; + std::string label_string(label.data(), label.length()); + SECStatus result = SSL_ExportKeyingMaterial( + nss_fd_, label_string.c_str(), + reinterpret_cast<const unsigned char*>(context.data()), + context.length(), out, outlen); + if (result != SECSuccess) { + LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", ""); + return MapNSSError(PORT_GetError()); + } + return OK; +} + SSLClientSocket::NextProtoStatus SSLClientSocketNSS::GetNextProto(std::string* proto) { #if defined(SSL_NEXT_PROTO_NEGOTIATED) diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h index 796de65..6a27d4c 100644 --- a/net/socket/ssl_client_socket_nss.h +++ b/net/socket/ssl_client_socket_nss.h @@ -61,6 +61,10 @@ class SSLClientSocketNSS : public SSLClientSocket { // SSLClientSocket methods: virtual void GetSSLInfo(SSLInfo* ssl_info); virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); + virtual int ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen); virtual NextProtoStatus GetNextProto(std::string* proto); // StreamSocket methods: diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index d1d17c8..0801bf4 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc @@ -596,6 +596,12 @@ void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( cert_request_info->client_certs = client_certs_; } +int SSLClientSocketOpenSSL::ExportKeyingMaterial( + const base::StringPiece& label, const base::StringPiece& context, + unsigned char *out, unsigned int outlen) { + return ERR_NOT_IMPLEMENTED; +} + SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( std::string* proto) { *proto = npn_proto_; diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h index 5f97388..e3529a4 100644 --- a/net/socket/ssl_client_socket_openssl.h +++ b/net/socket/ssl_client_socket_openssl.h @@ -55,6 +55,10 @@ class SSLClientSocketOpenSSL : public SSLClientSocket { // SSLClientSocket methods: virtual void GetSSLInfo(SSLInfo* ssl_info); virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); + virtual int ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen); virtual NextProtoStatus GetNextProto(std::string* proto); // StreamSocket methods: diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc index 4719857..729d76e 100644 --- a/net/socket/ssl_client_socket_win.cc +++ b/net/socket/ssl_client_socket_win.cc @@ -542,6 +542,13 @@ void SSLClientSocketWin::GetSSLCertRequestInfo( DCHECK(ok); } +int SSLClientSocketWin::ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen) { + return ERR_NOT_IMPLEMENTED; +} + SSLClientSocket::NextProtoStatus SSLClientSocketWin::GetNextProto(std::string* proto) { proto->clear(); diff --git a/net/socket/ssl_client_socket_win.h b/net/socket/ssl_client_socket_win.h index e7fa0a5..fb3d5a7 100644 --- a/net/socket/ssl_client_socket_win.h +++ b/net/socket/ssl_client_socket_win.h @@ -48,6 +48,10 @@ class SSLClientSocketWin : public SSLClientSocket { // SSLClientSocket methods: virtual void GetSSLInfo(SSLInfo* ssl_info); virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); + virtual int ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen); virtual NextProtoStatus GetNextProto(std::string* proto); // StreamSocket methods: diff --git a/net/socket/ssl_server_socket.h b/net/socket/ssl_server_socket.h index b0b7977..a1a7f9a 100644 --- a/net/socket/ssl_server_socket.h +++ b/net/socket/ssl_server_socket.h @@ -10,9 +10,13 @@ #include "net/base/net_api.h" #include "net/socket/stream_socket.h" +namespace base { +class StringPiece; +} // namespace base + namespace crypto { class RSAPrivateKey; -} // namespace base +} // namespace crypto namespace net { @@ -29,6 +33,14 @@ class SSLServerSocket : public StreamSocket { // completion then the callback will be silently, as for other StreamSocket // calls. virtual int Handshake(CompletionCallback* callback) = 0; + + // Exports data derived from the SSL master-secret (see RFC 5705). + // The call will fail with an error if the socket is not connected, or the + // SSL implementation does not support the operation. + virtual int ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen) = 0; }; // Creates an SSL server socket over an already-connected transport socket. diff --git a/net/socket/ssl_server_socket_nss.cc b/net/socket/ssl_server_socket_nss.cc index 83a382e..c364173 100644 --- a/net/socket/ssl_server_socket_nss.cc +++ b/net/socket/ssl_server_socket_nss.cc @@ -126,6 +126,24 @@ int SSLServerSocketNSS::Handshake(CompletionCallback* callback) { return rv > OK ? OK : rv; } +int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen) { + if (!IsConnected()) + return ERR_SOCKET_NOT_CONNECTED; + std::string label_string(label.data(), label.length()); + SECStatus result = SSL_ExportKeyingMaterial( + nss_fd_, label_string.c_str(), + reinterpret_cast<const unsigned char*>(context.data()), + context.length(), out, outlen); + if (result != SECSuccess) { + LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", ""); + return MapNSSError(PORT_GetError()); + } + return OK; +} + int SSLServerSocketNSS::Connect(CompletionCallback* callback) { NOTIMPLEMENTED(); return ERR_NOT_IMPLEMENTED; diff --git a/net/socket/ssl_server_socket_nss.h b/net/socket/ssl_server_socket_nss.h index 5903c17..9f13d4a 100644 --- a/net/socket/ssl_server_socket_nss.h +++ b/net/socket/ssl_server_socket_nss.h @@ -33,6 +33,10 @@ class SSLServerSocketNSS : public SSLServerSocket { // SSLServerSocket interface. virtual int Handshake(CompletionCallback* callback); + virtual int ExportKeyingMaterial(const base::StringPiece& label, + const base::StringPiece& context, + unsigned char *out, + unsigned int outlen); // Socket interface (via StreamSocket). virtual int Read(IOBuffer* buf, int buf_len, diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index 5962cfa..0097325 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc @@ -327,9 +327,9 @@ TEST_F(SSLServerSocketTest, Handshake) { Initialize(); TestCompletionCallback connect_callback; - TestCompletionCallback accept_callback; + TestCompletionCallback handshake_callback; - int server_ret = server_socket_->Handshake(&accept_callback); + int server_ret = server_socket_->Handshake(&handshake_callback); EXPECT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING); int client_ret = client_socket_->Connect(&connect_callback); @@ -339,7 +339,7 @@ TEST_F(SSLServerSocketTest, Handshake) { EXPECT_EQ(net::OK, connect_callback.WaitForResult()); } if (server_ret == net::ERR_IO_PENDING) { - EXPECT_EQ(net::OK, accept_callback.WaitForResult()); + EXPECT_EQ(net::OK, handshake_callback.WaitForResult()); } // Make sure the cert status is expected. @@ -352,20 +352,20 @@ TEST_F(SSLServerSocketTest, DataTransfer) { Initialize(); TestCompletionCallback connect_callback; - TestCompletionCallback accept_callback; + TestCompletionCallback handshake_callback; // Establish connection. int client_ret = client_socket_->Connect(&connect_callback); ASSERT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING); - int server_ret = server_socket_->Handshake(&accept_callback); + int server_ret = server_socket_->Handshake(&handshake_callback); ASSERT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING); if (client_ret == net::ERR_IO_PENDING) { ASSERT_EQ(net::OK, connect_callback.WaitForResult()); } if (server_ret == net::ERR_IO_PENDING) { - ASSERT_EQ(net::OK, accept_callback.WaitForResult()); + ASSERT_EQ(net::OK, handshake_callback.WaitForResult()); } const int kReadBufSize = 1024; @@ -406,6 +406,50 @@ TEST_F(SSLServerSocketTest, DataTransfer) { } EXPECT_EQ(0, memcmp(write_buf->data(), read_buf->data(), write_buf->size())); } + +// This test executes ExportKeyingMaterial() on the client and server sockets, +// after connecting them, and verifies that the results match. +// This test will fail if False Start is enabled (see crbug.com/90208). +TEST_F(SSLServerSocketTest, ExportKeyingMaterial) { + Initialize(); + + TestCompletionCallback connect_callback; + TestCompletionCallback handshake_callback; + + int client_ret = client_socket_->Connect(&connect_callback); + ASSERT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING); + + int server_ret = server_socket_->Handshake(&handshake_callback); + ASSERT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING); + + if (client_ret == net::ERR_IO_PENDING) { + ASSERT_EQ(net::OK, connect_callback.WaitForResult()); + } + if (server_ret == net::ERR_IO_PENDING) { + ASSERT_EQ(net::OK, handshake_callback.WaitForResult()); + } + + const int kKeyingMaterialSize = 32; + const char* kKeyingLabel = "EXPERIMENTAL-server-socket-test"; + const char* kKeyingContext = ""; + unsigned char server_out[kKeyingMaterialSize]; + int rv = server_socket_->ExportKeyingMaterial(kKeyingLabel, kKeyingContext, + server_out, sizeof(server_out)); + ASSERT_EQ(rv, net::OK); + + unsigned char client_out[kKeyingMaterialSize]; + rv = client_socket_->ExportKeyingMaterial(kKeyingLabel, kKeyingContext, + client_out, sizeof(client_out)); + ASSERT_EQ(rv, net::OK); + EXPECT_TRUE(memcmp(server_out, client_out, sizeof(server_out)) == 0); + + const char* kKeyingLabelBad = "EXPERIMENTAL-server-socket-test-bad"; + unsigned char client_bad[kKeyingMaterialSize]; + rv = client_socket_->ExportKeyingMaterial(kKeyingLabelBad, kKeyingContext, + client_bad, sizeof(client_bad)); + ASSERT_EQ(rv, net::OK); + EXPECT_TRUE(memcmp(server_out, client_bad, sizeof(server_out)) != 0); +} #endif } // namespace net |