summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornharper <nharper@chromium.org>2016-09-21 05:42:35 (GMT)
committerCommit bot <commit-bot@chromium.org>2016-09-21 05:45:24 (GMT)
commit78e6d2b3325b16d8b637b9457a775557e1ec7e0e (patch)
treea76eecfc765eb4af4bc7cb0f394810eea6deafde
parentd6a84dbb67c7d6a8eb47d76a34d0e2627670f026 (diff)
downloadchromium-78e6d2b3325b16d8b637b9457a775557e1ec7e0e.tar.gz
chromium-78e6d2b3325b16d8b637b9457a775557e1ec7e0e.tar.xz
Update Token Binding code to the latest drafts
draft-ietf-tokbind-protocol-10: - The TokenBinding.signature now closes over the token binding type. - Public key serialization is length prefixed to support parsing unknown key types. draft-ietf-tokbind-negotiation-05: - Require Renegotiation Indication draft-ietf-tokbind-https-06: - Sec-Token-Binding header base64 shouldn't include pad characters. - Include-Referred-Token-Binding-ID header's value is case insensitive. This also updates the tls and quic code to indicate support for draft version 10. BUG=467312 Review-Url: https://codereview.chromium.org/2337253004 Cr-Commit-Position: refs/heads/master@{#419981}
-rw-r--r--chrome/browser/extensions/api/socket/tls_socket_unittest.cc6
-rw-r--r--net/http/http_basic_stream.cc7
-rw-r--r--net/http/http_basic_stream.h5
-rw-r--r--net/http/http_network_transaction.cc13
-rw-r--r--net/http/http_network_transaction_unittest.cc10
-rw-r--r--net/http/http_response_body_drainer_unittest.cc5
-rw-r--r--net/http/http_stream.h11
-rw-r--r--net/http/http_stream_factory_impl_unittest.cc5
-rw-r--r--net/http/http_stream_parser.cc7
-rw-r--r--net/http/http_stream_parser.h6
-rw-r--r--net/http/proxy_connect_redirect_http_stream.cc3
-rw-r--r--net/http/proxy_connect_redirect_http_stream.h5
-rw-r--r--net/quic/chromium/quic_chromium_client_session.cc9
-rw-r--r--net/quic/chromium/quic_chromium_client_session.h9
-rw-r--r--net/quic/chromium/quic_http_stream.cc7
-rw-r--r--net/quic/chromium/quic_http_stream.h5
-rw-r--r--net/quic/chromium/quic_stream_factory.cc2
-rw-r--r--net/socket/fuzzed_socket_factory.cc5
-rw-r--r--net/socket/socket_test_util.cc11
-rw-r--r--net/socket/socket_test_util.h10
-rw-r--r--net/socket/ssl_client_socket.h11
-rw-r--r--net/socket/ssl_client_socket_impl.cc29
-rw-r--r--net/socket/ssl_client_socket_impl.h11
-rw-r--r--net/spdy/spdy_http_stream.cc7
-rw-r--r--net/spdy/spdy_http_stream.h5
-rw-r--r--net/spdy/spdy_session.cc7
-rw-r--r--net/spdy/spdy_session.h10
-rw-r--r--net/ssl/token_binding.cc56
-rw-r--r--net/ssl/token_binding.h33
-rw-r--r--net/url_request/url_request_http_job_unittest.cc5
-rw-r--r--net/url_request/url_request_job.cc1
-rw-r--r--net/url_request/url_request_unittest.cc26
-rw-r--r--net/websockets/websocket_basic_handshake_stream.cc3
-rw-r--r--net/websockets/websocket_basic_handshake_stream.h5
-rw-r--r--third_party/tlslite/README.chromium3
-rw-r--r--third_party/tlslite/patches/renegotiation_indication.patch86
-rw-r--r--third_party/tlslite/patches/token_binding_version.patch22
-rw-r--r--third_party/tlslite/tlslite/constants.py1
-rw-r--r--third_party/tlslite/tlslite/messages.py18
-rw-r--r--third_party/tlslite/tlslite/tlsconnection.py4
40 files changed, 348 insertions, 136 deletions
diff --git a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
index 812a99d..88134bd 100644
--- a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
+++ b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
@@ -73,8 +73,10 @@ class MockSSLClientSocket : public net::SSLClientSocket {
MOCK_CONST_METHOD0(GetUnverifiedServerCertificateChain,
scoped_refptr<net::X509Certificate>());
MOCK_CONST_METHOD0(GetChannelIDService, net::ChannelIDService*());
- MOCK_METHOD2(GetSignedEKMForTokenBinding,
- net::Error(crypto::ECPrivateKey*, std::vector<uint8_t>*));
+ MOCK_METHOD3(GetTokenBindingSignature,
+ net::Error(crypto::ECPrivateKey*,
+ net::TokenBindingType,
+ std::vector<uint8_t>*));
MOCK_CONST_METHOD0(GetChannelIDKey, crypto::ECPrivateKey*());
bool IsConnected() const override { return true; }
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc
index c908940..fb31dc4 100644
--- a/net/http/http_basic_stream.cc
+++ b/net/http/http_basic_stream.cc
@@ -111,9 +111,10 @@ bool HttpBasicStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
return state_.connection()->socket()->GetPeerAddress(endpoint) == OK;
}
-Error HttpBasicStream::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) {
- return parser()->GetSignedEKMForTokenBinding(key, out);
+Error HttpBasicStream::GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
+ return parser()->GetTokenBindingSignature(key, tb_type, out);
}
void HttpBasicStream::Drain(HttpNetworkSession* session) {
diff --git a/net/http/http_basic_stream.h b/net/http/http_basic_stream.h
index ed98021..1f3c419 100644
--- a/net/http/http_basic_stream.h
+++ b/net/http/http_basic_stream.h
@@ -78,8 +78,9 @@ class NET_EXPORT_PRIVATE HttpBasicStream : public HttpStream {
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
void Drain(HttpNetworkSession* session) override;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 10b6e12..d17ef21 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -1022,8 +1022,9 @@ int HttpNetworkTransaction::BuildRequestHeaders(
int HttpNetworkTransaction::BuildTokenBindingHeader(std::string* out) {
base::TimeTicks start = base::TimeTicks::Now();
std::vector<uint8_t> signed_ekm;
- int rv = stream_->GetSignedEKMForTokenBinding(
- provided_token_binding_key_.get(), &signed_ekm);
+ int rv = stream_->GetTokenBindingSignature(provided_token_binding_key_.get(),
+ TokenBindingType::PROVIDED,
+ &signed_ekm);
if (rv != OK)
return rv;
std::string provided_token_binding;
@@ -1039,8 +1040,9 @@ int HttpNetworkTransaction::BuildTokenBindingHeader(std::string* out) {
std::string referred_token_binding;
if (referred_token_binding_key_) {
std::vector<uint8_t> referred_signed_ekm;
- int rv = stream_->GetSignedEKMForTokenBinding(
- referred_token_binding_key_.get(), &referred_signed_ekm);
+ int rv = stream_->GetTokenBindingSignature(
+ referred_token_binding_key_.get(), TokenBindingType::REFERRED,
+ &referred_signed_ekm);
if (rv != OK)
return rv;
rv = BuildTokenBinding(TokenBindingType::REFERRED,
@@ -1054,8 +1056,7 @@ int HttpNetworkTransaction::BuildTokenBindingHeader(std::string* out) {
rv = BuildTokenBindingMessageFromTokenBindings(token_bindings, &header);
if (rv != OK)
return rv;
- base::Base64UrlEncode(header, base::Base64UrlEncodePolicy::INCLUDE_PADDING,
- out);
+ base::Base64UrlEncode(header, base::Base64UrlEncodePolicy::OMIT_PADDING, out);
base::TimeDelta header_creation_time = base::TimeTicks::Now() - start;
UMA_HISTOGRAM_CUSTOM_TIMES("Net.TokenBinding.HeaderCreationTime",
header_creation_time,
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index ae1cb31..000d7e1 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -14193,8 +14193,9 @@ class FakeStream : public HttpStream,
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override {
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override {
ADD_FAILURE();
return ERR_NOT_IMPLEMENTED;
}
@@ -14427,8 +14428,9 @@ class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase {
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override {
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override {
ADD_FAILURE();
return ERR_NOT_IMPLEMENTED;
}
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index abbb29c..1788d02 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -111,8 +111,9 @@ class MockHttpStream : public HttpStream {
void GetSSLInfo(SSLInfo* ssl_info) override {}
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {}
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override {
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override {
ADD_FAILURE();
return ERR_NOT_IMPLEMENTED;
}
diff --git a/net/http/http_stream.h b/net/http/http_stream.h
index a1e476e..0b8a037 100644
--- a/net/http/http_stream.h
+++ b/net/http/http_stream.h
@@ -22,6 +22,7 @@
#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
+#include "net/ssl/token_binding.h"
namespace crypto {
class ECPrivateKey;
@@ -157,10 +158,12 @@ class NET_EXPORT_PRIVATE HttpStream {
// and does not modify |endpoint| if it is unavailable.
virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) = 0;
- // Signs the EKM value for Token Binding from the TLS layer using |*key| and
- // puts the result in |*out|. Returns OK or ERR_FAILED.
- virtual Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) = 0;
+ // Generates the signature used in Token Binding using |*key| and for a Token
+ // Binding of type |tb_type|, putting the signature in |*out|. Returns OK or
+ // ERR_FAILED.
+ virtual Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) = 0;
// In the case of an HTTP error or redirect, flush the response body (usually
// a simple error or "this page has moved") so that we can re-use the
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index 4dedd60..39e4199 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -119,8 +119,9 @@ class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
void GetSSLInfo(SSLInfo* ssl_info) override {}
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {}
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override {
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override {
ADD_FAILURE();
return ERR_NOT_IMPLEMENTED;
}
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
index 766ebd3..bf5a41a 100644
--- a/net/http/http_stream_parser.cc
+++ b/net/http/http_stream_parser.cc
@@ -1165,15 +1165,16 @@ void HttpStreamParser::GetSSLCertRequestInfo(
}
}
-Error HttpStreamParser::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) {
+Error HttpStreamParser::GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
if (!request_->url.SchemeIsCryptographic() || !connection_->socket()) {
NOTREACHED();
return ERR_FAILED;
}
SSLClientSocket* ssl_socket =
static_cast<SSLClientSocket*>(connection_->socket());
- return ssl_socket->GetSignedEKMForTokenBinding(key, out);
+ return ssl_socket->GetTokenBindingSignature(key, tb_type, out);
}
int HttpStreamParser::EncodeChunk(const base::StringPiece& payload,
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h
index 806caa3..b07a63a 100644
--- a/net/http/http_stream_parser.h
+++ b/net/http/http_stream_parser.h
@@ -20,6 +20,7 @@
#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/log/net_log.h"
+#include "net/ssl/token_binding.h"
namespace net {
@@ -100,8 +101,9 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out);
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out);
// Encodes the given |payload| in the chunked format to |output|.
// Returns the number of bytes written to |output|. |output_size| should
diff --git a/net/http/proxy_connect_redirect_http_stream.cc b/net/http/proxy_connect_redirect_http_stream.cc
index 552dddf..0cdd3b3 100644
--- a/net/http/proxy_connect_redirect_http_stream.cc
+++ b/net/http/proxy_connect_redirect_http_stream.cc
@@ -102,8 +102,9 @@ bool ProxyConnectRedirectHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
return false;
}
-Error ProxyConnectRedirectHttpStream::GetSignedEKMForTokenBinding(
+Error ProxyConnectRedirectHttpStream::GetTokenBindingSignature(
crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
std::vector<uint8_t>* out) {
NOTREACHED();
return ERR_NOT_IMPLEMENTED;
diff --git a/net/http/proxy_connect_redirect_http_stream.h b/net/http/proxy_connect_redirect_http_stream.h
index f2dd19e..1a82a4c 100644
--- a/net/http/proxy_connect_redirect_http_stream.h
+++ b/net/http/proxy_connect_redirect_http_stream.h
@@ -58,8 +58,9 @@ class ProxyConnectRedirectHttpStream : public HttpStream {
void GetSSLInfo(SSLInfo* ssl_info) override;
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
void Drain(HttpNetworkSession* session) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc
index 506185a..dfaafea 100644
--- a/net/quic/chromium/quic_chromium_client_session.cc
+++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -591,7 +591,7 @@ bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const {
ssl_info->UpdateCertificateTransparencyInfo(*ct_verify_result_);
if (crypto_stream_->crypto_negotiated_params().token_binding_key_param ==
- kP256) {
+ kTB10) {
ssl_info->token_binding_negotiated = true;
ssl_info->token_binding_key_param = TB_PARAM_ECDSAP256;
}
@@ -601,6 +601,7 @@ bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const {
Error QuicChromiumClientSession::GetTokenBindingSignature(
crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
std::vector<uint8_t>* out) {
// The same key will be used across multiple requests to sign the same value,
// so the signature is cached.
@@ -608,7 +609,7 @@ Error QuicChromiumClientSession::GetTokenBindingSignature(
if (!key->ExportRawPublicKey(&raw_public_key))
return ERR_FAILED;
TokenBindingSignatureMap::iterator it =
- token_binding_signatures_.Get(raw_public_key);
+ token_binding_signatures_.Get(std::make_pair(tb_type, raw_public_key));
if (it != token_binding_signatures_.end()) {
*out = it->second;
return OK;
@@ -617,9 +618,9 @@ Error QuicChromiumClientSession::GetTokenBindingSignature(
std::string key_material;
if (!crypto_stream_->ExportTokenBindingKeyingMaterial(&key_material))
return ERR_FAILED;
- if (!SignTokenBindingEkm(key_material, key, out))
+ if (!CreateTokenBindingSignature(key_material, tb_type, key, out))
return ERR_FAILED;
- token_binding_signatures_.Put(raw_public_key, *out);
+ token_binding_signatures_.Put(std::make_pair(tb_type, raw_public_key), *out);
return OK;
}
diff --git a/net/quic/chromium/quic_chromium_client_session.h b/net/quic/chromium/quic_chromium_client_session.h
index f9aa8b8..61bb3a2 100644
--- a/net/quic/chromium/quic_chromium_client_session.h
+++ b/net/quic/chromium/quic_chromium_client_session.h
@@ -48,7 +48,8 @@ class SSLInfo;
class TransportSecurityState;
using TokenBindingSignatureMap =
- base::MRUCache<std::string, std::vector<uint8_t>>;
+ base::MRUCache<std::pair<TokenBindingType, std::string>,
+ std::vector<uint8_t>>;
namespace test {
class QuicChromiumClientSessionPeer;
@@ -197,9 +198,11 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// Gets the SSL connection information.
bool GetSSLInfo(SSLInfo* ssl_info) const;
- // Signs the exported keying material used for Token Binding using key |*key|
- // and puts the signature in |*out|. Returns a net error code.
+ // Generates the signature used in Token Binding using key |*key| and for a
+ // Token Binding of type |tb_type|, putting the signature in |*out|. Returns a
+ // net error code.
Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
std::vector<uint8_t>* out);
// Performs a crypto handshake with the server.
diff --git a/net/quic/chromium/quic_http_stream.cc b/net/quic/chromium/quic_http_stream.cc
index 9dd3181..79e5805 100644
--- a/net/quic/chromium/quic_http_stream.cc
+++ b/net/quic/chromium/quic_http_stream.cc
@@ -408,9 +408,10 @@ bool QuicHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
return true;
}
-Error QuicHttpStream::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) {
- return session_->GetTokenBindingSignature(key, out);
+Error QuicHttpStream::GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
+ return session_->GetTokenBindingSignature(key, tb_type, out);
}
void QuicHttpStream::Drain(HttpNetworkSession* session) {
diff --git a/net/quic/chromium/quic_http_stream.h b/net/quic/chromium/quic_http_stream.h
index cf6fb57..3cfd483 100644
--- a/net/quic/chromium/quic_http_stream.h
+++ b/net/quic/chromium/quic_http_stream.h
@@ -65,8 +65,9 @@ class NET_EXPORT_PRIVATE QuicHttpStream
void GetSSLInfo(SSLInfo* ssl_info) override;
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
void Drain(HttpNetworkSession* session) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
void SetPriority(RequestPriority priority) override;
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index a949274c..c0b86dc 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -816,7 +816,7 @@ QuicStreamFactory::QuicStreamFactory(
new ChannelIDSourceChromium(channel_id_service));
}
if (enable_token_binding && channel_id_service)
- crypto_config_.tb_key_params.push_back(kP256);
+ crypto_config_.tb_key_params.push_back(kTB10);
crypto::EnsureOpenSSLInit();
bool has_aes_hardware_support = !!EVP_has_aes_hardware();
UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.PreferAesGcm",
diff --git a/net/socket/fuzzed_socket_factory.cc b/net/socket/fuzzed_socket_factory.cc
index 34bf18c..23cd366 100644
--- a/net/socket/fuzzed_socket_factory.cc
+++ b/net/socket/fuzzed_socket_factory.cc
@@ -105,8 +105,9 @@ class FailingSSLClientSocket : public SSLClientSocket {
return nullptr;
}
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override {
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override {
NOTREACHED();
return ERR_UNEXPECTED;
}
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index e2b4d2f..1bc2622 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -833,8 +833,9 @@ ChannelIDService* MockClientSocket::GetChannelIDService() const {
return NULL;
}
-Error MockClientSocket::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) {
+Error MockClientSocket::GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
NOTREACHED();
return ERR_NOT_IMPLEMENTED;
}
@@ -1229,9 +1230,9 @@ ChannelIDService* MockSSLClientSocket::GetChannelIDService() const {
return data_->channel_id_service;
}
-Error MockSSLClientSocket::GetSignedEKMForTokenBinding(
- crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) {
+Error MockSSLClientSocket::GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
out->push_back('A');
return OK;
}
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 431b229..8665789 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -583,8 +583,9 @@ class MockClientSocket : public SSLClientSocket {
unsigned char* out,
unsigned int outlen) override;
ChannelIDService* GetChannelIDService() const override;
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
crypto::ECPrivateKey* GetChannelIDKey() const override;
protected:
@@ -699,8 +700,9 @@ class MockSSLClientSocket : public MockClientSocket, public AsyncSocket {
// SSLClientSocket implementation.
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
// This MockSocket does not implement the manual async IO feature.
void OnReadComplete(const MockRead& data) override;
void OnWriteComplete(int rv) override;
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h
index ba8142a..5d4e49b 100644
--- a/net/socket/ssl_client_socket.h
+++ b/net/socket/ssl_client_socket.h
@@ -16,6 +16,7 @@
#include "net/base/net_errors.h"
#include "net/socket/ssl_socket.h"
#include "net/socket/stream_socket.h"
+#include "net/ssl/token_binding.h"
namespace base {
class FilePath;
@@ -108,10 +109,12 @@ class NET_EXPORT SSLClientSocket : public SSLSocket {
// channel ids are not supported.
virtual ChannelIDService* GetChannelIDService() const = 0;
- // Signs the EKM value for Token Binding with |*key| and puts it in |*out|.
- // Returns a net error code.
- virtual Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) = 0;
+ // Generates the signature used in Token Binding using key |*key| and for a
+ // Token Binding of type |tb_type|, putting the signature in |*out|. Returns a
+ // net error code.
+ virtual Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) = 0;
// This method is only for debugging crbug.com/548423 and will be removed when
// that bug is closed. This returns the channel ID key that was used when
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc
index a0a8a3d..fba8e8a 100644
--- a/net/socket/ssl_client_socket_impl.cc
+++ b/net/socket/ssl_client_socket_impl.cc
@@ -78,9 +78,9 @@ const unsigned int kTbExtNum = 24;
// Token Binding ProtocolVersions supported.
const uint8_t kTbProtocolVersionMajor = 0;
-const uint8_t kTbProtocolVersionMinor = 8;
+const uint8_t kTbProtocolVersionMinor = 10;
const uint8_t kTbMinProtocolVersionMajor = 0;
-const uint8_t kTbMinProtocolVersionMinor = 6;
+const uint8_t kTbMinProtocolVersionMinor = 10;
bool EVP_MDToPrivateKeyHash(const EVP_MD* md, SSLPrivateKey::Hash* hash) {
switch (EVP_MD_type(md)) {
@@ -487,7 +487,7 @@ SSLClientSocketImpl::SSLClientSocketImpl(
channel_id_service_(context.channel_id_service),
tb_was_negotiated_(false),
tb_negotiated_param_(TB_PARAM_ECDSAP256),
- tb_signed_ekm_map_(10),
+ tb_signature_map_(10),
ssl_(NULL),
transport_bio_(NULL),
transport_(std::move(transport_socket)),
@@ -534,16 +534,16 @@ ChannelIDService* SSLClientSocketImpl::GetChannelIDService() const {
return channel_id_service_;
}
-Error SSLClientSocketImpl::GetSignedEKMForTokenBinding(
- crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) {
+Error SSLClientSocketImpl::GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
// The same key will be used across multiple requests to sign the same value,
// so the signature is cached.
std::string raw_public_key;
if (!key->ExportRawPublicKey(&raw_public_key))
return ERR_FAILED;
- SignedEkmMap::iterator it = tb_signed_ekm_map_.Get(raw_public_key);
- if (it != tb_signed_ekm_map_.end()) {
+ auto it = tb_signature_map_.Get(std::make_pair(tb_type, raw_public_key));
+ if (it != tb_signature_map_.end()) {
*out = it->second;
return OK;
}
@@ -557,13 +557,13 @@ Error SSLClientSocketImpl::GetSignedEKMForTokenBinding(
return ERR_FAILED;
}
- if (!SignTokenBindingEkm(
+ if (!CreateTokenBindingSignature(
base::StringPiece(reinterpret_cast<char*>(tb_ekm_buf),
sizeof(tb_ekm_buf)),
- key, out))
+ tb_type, key, out))
return ERR_FAILED;
- tb_signed_ekm_map_.Put(raw_public_key, *out);
+ tb_signature_map_.Put(std::make_pair(tb_type, raw_public_key), *out);
return OK;
}
@@ -1171,9 +1171,12 @@ int SSLClientSocketImpl::DoHandshakeComplete(int result) {
}
// Check that if token binding was negotiated, then extended master secret
- // must also be negotiated.
- if (tb_was_negotiated_ && !SSL_get_extms_support(ssl_))
+ // and renegotiation indication must also be negotiated.
+ if (tb_was_negotiated_ &&
+ !(SSL_get_extms_support(ssl_) &&
+ SSL_get_secure_renegotiation_support(ssl_))) {
return ERR_SSL_PROTOCOL_ERROR;
+ }
const uint8_t* alpn_proto = NULL;
unsigned alpn_len = 0;
diff --git a/net/socket/ssl_client_socket_impl.h b/net/socket/ssl_client_socket_impl.h
index f882636..e6d1cc9 100644
--- a/net/socket/ssl_client_socket_impl.h
+++ b/net/socket/ssl_client_socket_impl.h
@@ -44,7 +44,9 @@ class CTVerifier;
class SSLCertRequestInfo;
class SSLInfo;
-using SignedEkmMap = base::MRUCache<std::string, std::vector<uint8_t>>;
+using TokenBindingSignatureMap =
+ base::MRUCache<std::pair<TokenBindingType, std::string>,
+ std::vector<uint8_t>>;
class SSLClientSocketImpl : public SSLClientSocket {
public:
@@ -74,8 +76,9 @@ class SSLClientSocketImpl : public SSLClientSocket {
// SSLClientSocket implementation.
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
ChannelIDService* GetChannelIDService() const override;
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
crypto::ECPrivateKey* GetChannelIDKey() const override;
// SSLSocket implementation.
@@ -319,7 +322,7 @@ class SSLClientSocketImpl : public SSLClientSocket {
ChannelIDService* channel_id_service_;
bool tb_was_negotiated_;
TokenBindingParam tb_negotiated_param_;
- SignedEkmMap tb_signed_ekm_map_;
+ TokenBindingSignatureMap tb_signature_map_;
// OpenSSL stuff
SSL* ssl_;
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index 4b45146..0fdbcdf 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -591,9 +591,10 @@ bool SpdyHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
return spdy_session_->GetPeerAddress(endpoint) == OK;
}
-Error SpdyHttpStream::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) {
- return spdy_session_->GetSignedEKMForTokenBinding(key, out);
+Error SpdyHttpStream::GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
+ return spdy_session_->GetTokenBindingSignature(key, tb_type, out);
}
void SpdyHttpStream::Drain(HttpNetworkSession* session) {
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h
index c2b3121..e7af95c 100644
--- a/net/spdy/spdy_http_stream.h
+++ b/net/spdy/spdy_http_stream.h
@@ -79,8 +79,9 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
void GetSSLInfo(SSLInfo* ssl_info) override;
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
void Drain(HttpNetworkSession* session) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
void SetPriority(RequestPriority priority) override;
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 6b3fc026..d3e1e2e 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -1936,15 +1936,16 @@ NextProto SpdySession::GetNegotiatedProtocol() const {
return connection_->socket()->GetNegotiatedProtocol();
}
-Error SpdySession::GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) {
+Error SpdySession::GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) {
if (!is_secure_) {
NOTREACHED();
return ERR_FAILED;
}
SSLClientSocket* ssl_socket =
static_cast<SSLClientSocket*>(connection_->socket());
- return ssl_socket->GetSignedEKMForTokenBinding(key, out);
+ return ssl_socket->GetTokenBindingSignature(key, tb_type, out);
}
void SpdySession::OnError(SpdyFramer::SpdyError error_code) {
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index 0e0d08b..f9ce0cb 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -415,10 +415,12 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// Returns the protocol negotiated via ALPN for the underlying socket.
NextProto GetNegotiatedProtocol() const;
- // Signs the EKM value for Token Binding from the TLS layer using |*key| and
- // puts the result in |*out|. Returns OK or ERR_FAILED.
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out);
+ // Generates the signature used in Token Binding using |*key| and for a Token
+ // Binding of type |tb_type|, putting the signature in |*out|. Returns a net
+ // error code of OK or ERR_FAILED.
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out);
// Send a WINDOW_UPDATE frame for a stream. Called by a stream
// whenever receive window size is increased.
diff --git a/net/ssl/token_binding.cc b/net/ssl/token_binding.cc
index 63fc9db..f3f2dc0 100644
--- a/net/ssl/token_binding.cc
+++ b/net/ssl/token_binding.cc
@@ -32,9 +32,10 @@ bool BuildTokenBindingID(crypto::ECPrivateKey* key, CBB* out) {
NULL) != kUncompressedPointLen) {
return false;
}
- CBB ec_point;
+ CBB public_key, ec_point;
return CBB_add_u8(out, TB_PARAM_ECDSAP256) &&
- CBB_add_u8_length_prefixed(out, &ec_point) &&
+ CBB_add_u16_length_prefixed(out, &public_key) &&
+ CBB_add_u8_length_prefixed(&public_key, &ec_point) &&
CBB_add_bytes(&ec_point, point_buf + 1, kUncompressedPointLen - 1) &&
CBB_flush(out);
}
@@ -68,14 +69,26 @@ ECDSA_SIG* RawToECDSA_SIG(EC_KEY* ec, base::StringPiece sig) {
} // namespace
-bool SignTokenBindingEkm(base::StringPiece ekm,
- crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) {
- const uint8_t* ekm_data = reinterpret_cast<const uint8_t*>(ekm.data());
+bool CreateTokenBindingSignature(base::StringPiece ekm,
+ TokenBindingType type,
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out) {
+ crypto::ScopedEVP_MD_CTX digest_ctx(EVP_MD_CTX_create());
+ uint8_t tb_type = static_cast<uint8_t>(type);
+ uint8_t key_type = static_cast<uint8_t>(TB_PARAM_ECDSAP256);
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned int digest_len;
+ if (!EVP_DigestInit(digest_ctx.get(), EVP_sha256()) ||
+ !EVP_DigestUpdate(digest_ctx.get(), &tb_type, 1) ||
+ !EVP_DigestUpdate(digest_ctx.get(), &key_type, 1) ||
+ !EVP_DigestUpdate(digest_ctx.get(), ekm.data(), ekm.size()) ||
+ !EVP_DigestFinal_ex(digest_ctx.get(), digest, &digest_len)) {
+ return false;
+ }
EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key->key());
if (!ec_key)
return false;
- crypto::ScopedECDSA_SIG sig(ECDSA_do_sign(ekm_data, ekm.size(), ec_key));
+ crypto::ScopedECDSA_SIG sig(ECDSA_do_sign(digest, digest_len, ec_key));
if (!sig)
return false;
return ECDSA_SIGToRaw(sig.get(), ec_key, out);
@@ -137,7 +150,7 @@ TokenBinding::TokenBinding() {}
bool ParseTokenBindingMessage(base::StringPiece token_binding_message,
std::vector<TokenBinding>* token_bindings) {
- CBS tb_message, tb, ec_point, signature, extensions;
+ CBS tb_message, tb, public_key, ec_point, signature, extensions;
uint8_t tb_type, tb_param;
CBS_init(&tb_message,
reinterpret_cast<const uint8_t*>(token_binding_message.data()),
@@ -146,7 +159,9 @@ bool ParseTokenBindingMessage(base::StringPiece token_binding_message,
return false;
while (CBS_len(&tb)) {
if (!CBS_get_u8(&tb, &tb_type) || !CBS_get_u8(&tb, &tb_param) ||
- !CBS_get_u8_length_prefixed(&tb, &ec_point) ||
+ !CBS_get_u16_length_prefixed(&tb, &public_key) ||
+ !CBS_get_u8_length_prefixed(&public_key, &ec_point) ||
+ CBS_len(&public_key) != 0 ||
!CBS_get_u16_length_prefixed(&tb, &signature) ||
!CBS_get_u16_length_prefixed(&tb, &extensions) ||
tb_param != TB_PARAM_ECDSAP256 ||
@@ -167,9 +182,10 @@ bool ParseTokenBindingMessage(base::StringPiece token_binding_message,
return true;
}
-bool VerifyEKMSignature(base::StringPiece ec_point,
- base::StringPiece signature,
- base::StringPiece ekm) {
+bool VerifyTokenBindingSignature(base::StringPiece ec_point,
+ base::StringPiece signature,
+ TokenBindingType type,
+ base::StringPiece ekm) {
if (ec_point.size() != kUncompressedPointLen - 1)
return false;
uint8_t x9_62_ec_point[kUncompressedPointLen];
@@ -184,11 +200,23 @@ bool VerifyEKMSignature(base::StringPiece ec_point,
return false;
}
+ crypto::ScopedEVP_MD_CTX digest_ctx(EVP_MD_CTX_create());
+ uint8_t tb_type = static_cast<uint8_t>(type);
+ uint8_t key_type = static_cast<uint8_t>(TB_PARAM_ECDSAP256);
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned int digest_len;
+ if (!EVP_DigestInit(digest_ctx.get(), EVP_sha256()) ||
+ !EVP_DigestUpdate(digest_ctx.get(), &tb_type, 1) ||
+ !EVP_DigestUpdate(digest_ctx.get(), &key_type, 1) ||
+ !EVP_DigestUpdate(digest_ctx.get(), ekm.data(), ekm.size()) ||
+ !EVP_DigestFinal_ex(digest_ctx.get(), digest, &digest_len)) {
+ return false;
+ }
+
crypto::ScopedECDSA_SIG sig(RawToECDSA_SIG(keyp, signature));
if (!sig)
return false;
- return !!ECDSA_do_verify(reinterpret_cast<const uint8_t*>(ekm.data()),
- ekm.size(), sig.get(), keyp);
+ return !!ECDSA_do_verify(digest, digest_len, sig.get(), keyp);
}
} // namespace net
diff --git a/net/ssl/token_binding.h b/net/ssl/token_binding.h
index a984850..9400093 100644
--- a/net/ssl/token_binding.h
+++ b/net/ssl/token_binding.h
@@ -20,12 +20,16 @@ enum class TokenBindingType {
REFERRED = 1,
};
-// Takes an exported keying material value |ekm| from the TLS layer and a token
-// binding key |key| and signs the EKM, putting the signature in |*out|. Returns
-// true on success or false if there's an error in the signing operations.
-bool SignTokenBindingEkm(base::StringPiece ekm,
- crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out);
+// Takes an exported keying material value |ekm| from the TLS layer, the type of
+// Token Binding |type|, and a token binding key |key| and concatenates the
+// Token Binding type, key type, and ekm. This concatenation is signed with
+// |key| in accordance with section 3.3 of draft-ietf-tokbind-protocol-10, with
+// the signature written to |*out|. Returns true on success or false if there's
+// an error in the signing operations.
+bool CreateTokenBindingSignature(base::StringPiece ekm,
+ TokenBindingType type,
+ crypto::ECPrivateKey* key,
+ std::vector<uint8_t>* out);
// Given a vector of serialized TokenBinding structs (as defined in
// draft-ietf-tokbind-protocol-04), this function combines them to form the
@@ -99,14 +103,15 @@ NET_EXPORT_PRIVATE bool ParseTokenBindingMessage(
base::StringPiece token_binding_message,
std::vector<TokenBinding>* token_bindings);
-// Takes an ECPoint |ec_point| from a TokenBindingID and |signature| from a
-// TokenBinding and verifies that |signature| is the signature of |ekm| using
-// |ec_point| as the public key. Returns true if the signature verifies and
-// false if it doesn't or some other error occurs in verification. This function
-// is only provided for testing.
-NET_EXPORT_PRIVATE bool VerifyEKMSignature(base::StringPiece ec_point,
- base::StringPiece signature,
- base::StringPiece ekm);
+// Takes an ECPoint |ec_point| from a TokenBindingID, |signature| from a
+// TokenBinding, and a Token Binding type |type| and verifies that |signature|
+// is the signature of |ekm| using |ec_point| as the public key. Returns true if
+// the signature verifies and false if it doesn't or some other error occurs in
+// verification. This function is only provided for testing.
+NET_EXPORT_PRIVATE bool VerifyTokenBindingSignature(base::StringPiece ec_point,
+ base::StringPiece signature,
+ TokenBindingType type,
+ base::StringPiece ekm);
} // namespace net
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc
index 1502903..8bc38b3 100644
--- a/net/url_request/url_request_http_job_unittest.cc
+++ b/net/url_request/url_request_http_job_unittest.cc
@@ -894,8 +894,9 @@ class FakeWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override {
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override {
ADD_FAILURE();
return ERR_NOT_IMPLEMENTED;
}
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index b40b822..bbd0800 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -974,6 +974,7 @@ RedirectInfo URLRequestJob::ComputeRedirectInfo(const GURL& location,
std::string include_referer;
request_->GetResponseHeaderByName("include-referred-token-binding-id",
&include_referer);
+ include_referer = base::ToLowerASCII(include_referer);
if (include_referer == "true" &&
request_->ssl_info().token_binding_negotiated) {
redirect_info.referred_token_binding_host = url.host();
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index f2203e0..fece053 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -3421,7 +3421,7 @@ TEST_F(TokenBindingURLRequestTest, TokenBindingTest) {
EXPECT_TRUE(headers.GetHeader(HttpRequestHeaders::kTokenBinding,
&token_binding_header));
EXPECT_TRUE(base::Base64UrlDecode(
- token_binding_header, base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ token_binding_header, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
&token_binding_message));
std::vector<TokenBinding> token_bindings;
ASSERT_TRUE(
@@ -3432,8 +3432,9 @@ TEST_F(TokenBindingURLRequestTest, TokenBindingTest) {
std::string ekm = d.data_received();
EXPECT_EQ(TokenBindingType::PROVIDED, token_bindings[0].type);
- EXPECT_TRUE(VerifyEKMSignature(token_bindings[0].ec_point,
- token_bindings[0].signature, ekm));
+ EXPECT_TRUE(VerifyTokenBindingSignature(token_bindings[0].ec_point,
+ token_bindings[0].signature,
+ TokenBindingType::PROVIDED, ekm));
}
}
@@ -3464,7 +3465,7 @@ TEST_F(TokenBindingURLRequestTest, ForwardTokenBinding) {
EXPECT_TRUE(headers.GetHeader(HttpRequestHeaders::kTokenBinding,
&token_binding_header));
EXPECT_TRUE(base::Base64UrlDecode(
- token_binding_header, base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ token_binding_header, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
&token_binding_message));
std::vector<TokenBinding> token_bindings;
ASSERT_TRUE(
@@ -3475,11 +3476,13 @@ TEST_F(TokenBindingURLRequestTest, ForwardTokenBinding) {
std::string ekm = d.data_received();
EXPECT_EQ(TokenBindingType::PROVIDED, token_bindings[0].type);
- EXPECT_TRUE(VerifyEKMSignature(token_bindings[0].ec_point,
- token_bindings[0].signature, ekm));
+ EXPECT_TRUE(VerifyTokenBindingSignature(token_bindings[0].ec_point,
+ token_bindings[0].signature,
+ TokenBindingType::PROVIDED, ekm));
EXPECT_EQ(TokenBindingType::REFERRED, token_bindings[1].type);
- EXPECT_TRUE(VerifyEKMSignature(token_bindings[1].ec_point,
- token_bindings[1].signature, ekm));
+ EXPECT_TRUE(VerifyTokenBindingSignature(token_bindings[1].ec_point,
+ token_bindings[1].signature,
+ TokenBindingType::REFERRED, ekm));
}
}
@@ -3517,7 +3520,7 @@ TEST_F(TokenBindingURLRequestTest, DontForwardHeaderFromHttp) {
EXPECT_TRUE(headers.GetHeader(HttpRequestHeaders::kTokenBinding,
&token_binding_header));
EXPECT_TRUE(base::Base64UrlDecode(
- token_binding_header, base::Base64UrlDecodePolicy::REQUIRE_PADDING,
+ token_binding_header, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
&token_binding_message));
std::vector<TokenBinding> token_bindings;
ASSERT_TRUE(
@@ -3528,8 +3531,9 @@ TEST_F(TokenBindingURLRequestTest, DontForwardHeaderFromHttp) {
std::string ekm = d.data_received();
EXPECT_EQ(TokenBindingType::PROVIDED, token_bindings[0].type);
- EXPECT_TRUE(VerifyEKMSignature(token_bindings[0].ec_point,
- token_bindings[0].signature, ekm));
+ EXPECT_TRUE(VerifyTokenBindingSignature(token_bindings[0].ec_point,
+ token_bindings[0].signature,
+ TokenBindingType::PROVIDED, ekm));
}
}
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc
index ae6062ea9..424033b 100644
--- a/net/websockets/websocket_basic_handshake_stream.cc
+++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -447,8 +447,9 @@ void WebSocketBasicHandshakeStream::PopulateNetErrorDetails(
return;
}
-Error WebSocketBasicHandshakeStream::GetSignedEKMForTokenBinding(
+Error WebSocketBasicHandshakeStream::GetTokenBindingSignature(
crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
std::vector<uint8_t>* out) {
NOTREACHED();
return ERR_NOT_IMPLEMENTED;
diff --git a/net/websockets/websocket_basic_handshake_stream.h b/net/websockets/websocket_basic_handshake_stream.h
index d5b749c..59e7d50 100644
--- a/net/websockets/websocket_basic_handshake_stream.h
+++ b/net/websockets/websocket_basic_handshake_stream.h
@@ -65,8 +65,9 @@ class NET_EXPORT_PRIVATE WebSocketBasicHandshakeStream
void GetSSLInfo(SSLInfo* ssl_info) override;
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
- Error GetSignedEKMForTokenBinding(crypto::ECPrivateKey* key,
- std::vector<uint8_t>* out) override;
+ Error GetTokenBindingSignature(crypto::ECPrivateKey* key,
+ TokenBindingType tb_type,
+ std::vector<uint8_t>* out) override;
void Drain(HttpNetworkSession* session) override;
void SetPriority(RequestPriority priority) override;
void PopulateNetErrorDetails(NetErrorDetails* details) override;
diff --git a/third_party/tlslite/README.chromium b/third_party/tlslite/README.chromium
index aa3a901..c2d1f27 100644
--- a/third_party/tlslite/README.chromium
+++ b/third_party/tlslite/README.chromium
@@ -53,3 +53,6 @@ Local Modifications:
- patches/save_randoms.patch: Save client and server randoms when resuming
sessions.
- patches/alpn.path: Implement Application-Layer Protocol Negotiation Extension.
+- patches/token_binding_version.patch: Update Token Binding version number.
+- patches/renegotiation_indication.patch: Implement the renegotiation
+ indication extension (RFC 5746) without supporting renegotiation.
diff --git a/third_party/tlslite/patches/renegotiation_indication.patch b/third_party/tlslite/patches/renegotiation_indication.patch
new file mode 100644
index 0000000..69a1d7b
--- /dev/null
+++ b/third_party/tlslite/patches/renegotiation_indication.patch
@@ -0,0 +1,86 @@
+diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
+index e9743e4..82e8c07 100644
+--- a/third_party/tlslite/tlslite/constants.py
++++ b/third_party/tlslite/tlslite/constants.py
+@@ -61,6 +61,7 @@ class ExtensionType: # RFC 6066 / 4366
+ tack = 0xF300
+ supports_npn = 13172
+ channel_id = 30032
++ renegotiation_info = 0xFF01 # RFC 5746
+
+ class HashAlgorithm:
+ none = 0
+diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
+index 1ce9320..ac7e563 100644
+--- a/third_party/tlslite/tlslite/messages.py
++++ b/third_party/tlslite/tlslite/messages.py
+@@ -140,6 +140,7 @@ class ClientHello(HandshakeMsg):
+ self.tb_client_params = []
+ self.support_signed_cert_timestamps = False
+ self.status_request = False
++ self.ri = False
+
+ def create(self, version, random, session_id, cipher_suites,
+ certificate_types=None, srpUsername=None,
+@@ -244,12 +245,20 @@ class ClientHello(HandshakeMsg):
+ # request_extensions in the OCSP request.
+ p.getFixBytes(extLength)
+ self.status_request = True
++ elif extType == ExtensionType.renegotiation_info:
++ # We don't support renegotiation, so if we receive this
++ # extension, it should contain a single null byte.
++ if extLength != 1 or p.getFixBytes(extLength)[0] != 0:
++ raise SyntaxError()
++ self.ri = True
+ else:
+ _ = p.getFixBytes(extLength)
+ index2 = p.index
+ if index2 - index1 != extLength:
+ raise SyntaxError("Bad length for extension_data")
+ soFar += 4 + extLength
++ if CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV in self.cipher_suites:
++ self.ri = True
+ p.stopLengthCheck()
+ return self
+
+@@ -327,6 +336,7 @@ class ServerHello(HandshakeMsg):
+ self.tb_params = None
+ self.signed_cert_timestamps = None
+ self.status_request = False
++ self.send_ri = False
+
+ def create(self, version, random, session_id, cipher_suite,
+ certificate_type, tackExt, alpn_proto_selected,
+@@ -432,6 +442,10 @@ class ServerHello(HandshakeMsg):
+ if self.status_request:
+ w2.add(ExtensionType.status_request, 2)
+ w2.add(0, 2)
++ if self.send_ri:
++ w2.add(ExtensionType.renegotiation_info, 2)
++ w2.add(1, 2)
++ w2.add(0, 1)
+ if len(w2.bytes):
+ w.add(len(w2.bytes), 2)
+ w.bytes += w2.bytes
+diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
+index de5d580..8ba1c6e 100644
+--- a/third_party/tlslite/tlslite/tlsconnection.py
++++ b/third_party/tlslite/tlslite/tlsconnection.py
+@@ -1370,6 +1370,8 @@ class TLSConnection(TLSRecordLayer):
+ serverHello.signed_cert_timestamps = signedCertTimestamps
+ if clientHello.status_request:
+ serverHello.status_request = ocspResponse
++ if clientHello.ri:
++ serverHello.send_ri = True
+
+ # Perform the SRP key exchange
+ clientCertChain = None
+@@ -1583,6 +1585,8 @@ class TLSConnection(TLSRecordLayer):
+ if param in settings.supportedTokenBindingParams:
+ serverHello.tb_params = param
+ break
++ if clientHello.ri:
++ serverHello.send_ri = True
+ for result in self._sendMsg(serverHello):
+ yield result
+
diff --git a/third_party/tlslite/patches/token_binding_version.patch b/third_party/tlslite/patches/token_binding_version.patch
new file mode 100644
index 0000000..72567d5
--- /dev/null
+++ b/third_party/tlslite/patches/token_binding_version.patch
@@ -0,0 +1,22 @@
+diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
+index 1ce9320..ac7e563 100644
+--- a/third_party/tlslite/tlslite/messages.py
++++ b/third_party/tlslite/tlslite/messages.py
+@@ -223,7 +224,7 @@ class ClientHello(HandshakeMsg):
+ p2 = Parser(tokenBindingBytes)
+ ver_minor = p2.get(1)
+ ver_major = p2.get(1)
+- if (ver_major, ver_minor) >= (0, 6):
++ if (ver_major, ver_minor) >= (0, 10):
+ p2.startLengthCheck(1)
+ while not p2.atLengthCheck():
+ self.tb_client_params.append(p2.get(1))
+@@ -421,7 +431,7 @@ class ServerHello(HandshakeMsg):
+ w2.add(4, 2)
+ # version
+ w2.add(0, 1)
+- w2.add(6, 1)
++ w2.add(10, 1)
+ # length of params (defined as variable length <1..2^8-1>, but in
+ # this context the server can only send a single value.
+ w2.add(1, 1)
diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
index e9743e4..82e8c07 100644
--- a/third_party/tlslite/tlslite/constants.py
+++ b/third_party/tlslite/tlslite/constants.py
@@ -61,6 +61,7 @@ class ExtensionType: # RFC 6066 / 4366
tack = 0xF300
supports_npn = 13172
channel_id = 30032
+ renegotiation_info = 0xFF01 # RFC 5746
class HashAlgorithm:
none = 0
diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
index 1ce9320..ac7e563 100644
--- a/third_party/tlslite/tlslite/messages.py
+++ b/third_party/tlslite/tlslite/messages.py
@@ -140,6 +140,7 @@ class ClientHello(HandshakeMsg):
self.tb_client_params = []
self.support_signed_cert_timestamps = False
self.status_request = False
+ self.ri = False
def create(self, version, random, session_id, cipher_suites,
certificate_types=None, srpUsername=None,
@@ -223,7 +224,7 @@ class ClientHello(HandshakeMsg):
p2 = Parser(tokenBindingBytes)
ver_minor = p2.get(1)
ver_major = p2.get(1)
- if (ver_major, ver_minor) >= (0, 6):
+ if (ver_major, ver_minor) >= (0, 10):
p2.startLengthCheck(1)
while not p2.atLengthCheck():
self.tb_client_params.append(p2.get(1))
@@ -244,12 +245,20 @@ class ClientHello(HandshakeMsg):
# request_extensions in the OCSP request.
p.getFixBytes(extLength)
self.status_request = True
+ elif extType == ExtensionType.renegotiation_info:
+ # We don't support renegotiation, so if we receive this
+ # extension, it should contain a single null byte.
+ if extLength != 1 or p.getFixBytes(extLength)[0] != 0:
+ raise SyntaxError()
+ self.ri = True
else:
_ = p.getFixBytes(extLength)
index2 = p.index
if index2 - index1 != extLength:
raise SyntaxError("Bad length for extension_data")
soFar += 4 + extLength
+ if CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV in self.cipher_suites:
+ self.ri = True
p.stopLengthCheck()
return self
@@ -327,6 +336,7 @@ class ServerHello(HandshakeMsg):
self.tb_params = None
self.signed_cert_timestamps = None
self.status_request = False
+ self.send_ri = False
def create(self, version, random, session_id, cipher_suite,
certificate_type, tackExt, alpn_proto_selected,
@@ -421,7 +431,7 @@ class ServerHello(HandshakeMsg):
w2.add(4, 2)
# version
w2.add(0, 1)
- w2.add(6, 1)
+ w2.add(10, 1)
# length of params (defined as variable length <1..2^8-1>, but in
# this context the server can only send a single value.
w2.add(1, 1)
@@ -432,6 +442,10 @@ class ServerHello(HandshakeMsg):
if self.status_request:
w2.add(ExtensionType.status_request, 2)
w2.add(0, 2)
+ if self.send_ri:
+ w2.add(ExtensionType.renegotiation_info, 2)
+ w2.add(1, 2)
+ w2.add(0, 1)
if len(w2.bytes):
w.add(len(w2.bytes), 2)
w.bytes += w2.bytes
diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
index de5d580..8ba1c6e 100644
--- a/third_party/tlslite/tlslite/tlsconnection.py
+++ b/third_party/tlslite/tlslite/tlsconnection.py
@@ -1370,6 +1370,8 @@ class TLSConnection(TLSRecordLayer):
serverHello.signed_cert_timestamps = signedCertTimestamps
if clientHello.status_request:
serverHello.status_request = ocspResponse
+ if clientHello.ri:
+ serverHello.send_ri = True
# Perform the SRP key exchange
clientCertChain = None
@@ -1583,6 +1585,8 @@ class TLSConnection(TLSRecordLayer):
if param in settings.supportedTokenBindingParams:
serverHello.tb_params = param
break
+ if clientHello.ri:
+ serverHello.send_ri = True
for result in self._sendMsg(serverHello):
yield result