summaryrefslogtreecommitdiffstats
path: root/net/socket
diff options
context:
space:
mode:
authorwez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-23 05:12:39 +0000
committerwez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-23 05:12:39 +0000
commitb0ff3f8e755f87da1aedeaf051b88f53662f8652 (patch)
tree446118d1debf5c4b626a156f4be19db7e5dbbe05 /net/socket
parent5ef4e231a73a0a5910597c53f69592a11326ea54 (diff)
downloadchromium_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.cc2
-rw-r--r--net/socket/socket_test_util.cc8
-rw-r--r--net/socket/socket_test_util.h4
-rw-r--r--net/socket/ssl_client_socket.h12
-rw-r--r--net/socket/ssl_client_socket_mac.cc7
-rw-r--r--net/socket/ssl_client_socket_mac.h4
-rw-r--r--net/socket/ssl_client_socket_nss.cc18
-rw-r--r--net/socket/ssl_client_socket_nss.h4
-rw-r--r--net/socket/ssl_client_socket_openssl.cc6
-rw-r--r--net/socket/ssl_client_socket_openssl.h4
-rw-r--r--net/socket/ssl_client_socket_win.cc7
-rw-r--r--net/socket/ssl_client_socket_win.h4
-rw-r--r--net/socket/ssl_server_socket.h14
-rw-r--r--net/socket/ssl_server_socket_nss.cc18
-rw-r--r--net/socket/ssl_server_socket_nss.h4
-rw-r--r--net/socket/ssl_server_socket_unittest.cc56
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