Index: net/socket/ssl_client_socket_openssl.cc |
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc |
index 393e718672fb2a2cacf630b9a4c67c116f19e024..820feb2518b690fc2fe8e513553d3366ca81ec06 100644 |
--- a/net/socket/ssl_client_socket_openssl.cc |
+++ b/net/socket/ssl_client_socket_openssl.cc |
@@ -526,6 +526,7 @@ SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( |
channel_id_service_(context.channel_id_service), |
tb_was_negotiated_(false), |
tb_negotiated_param_(TB_PARAM_ECDSAP256), |
+ tb_signed_ekm_map_(10), |
ssl_(NULL), |
transport_bio_(NULL), |
transport_(std::move(transport_socket)), |
@@ -577,6 +578,47 @@ SSLClientSocketOpenSSL::GetChannelIDService() const { |
return channel_id_service_; |
} |
+Error SSLClientSocketOpenSSL::GetSignedEKMForTokenBinding( |
+ crypto::ECPrivateKey* key, |
+ 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()) { |
+ *out = it->second; |
+ return OK; |
+ } |
+ |
+ uint8_t tb_ekm_buf[32]; |
+ static const char kTokenBindingExporterLabel[] = "EXPORTER-Token-Binding"; |
+ if (!SSL_export_keying_material(ssl_, tb_ekm_buf, sizeof(tb_ekm_buf), |
+ kTokenBindingExporterLabel, |
+ strlen(kTokenBindingExporterLabel), nullptr, |
+ 0, false /* no context */)) { |
+ return ERR_FAILED; |
+ } |
+ |
+ size_t sig_len; |
+ crypto::ScopedEVP_PKEY_CTX pctx(EVP_PKEY_CTX_new(key->key(), nullptr)); |
+ if (!EVP_PKEY_sign_init(pctx.get()) || |
+ !EVP_PKEY_sign(pctx.get(), nullptr, &sig_len, tb_ekm_buf, |
+ sizeof(tb_ekm_buf))) { |
+ return ERR_FAILED; |
+ } |
+ out->resize(sig_len); |
+ if (!EVP_PKEY_sign(pctx.get(), out->data(), &sig_len, tb_ekm_buf, |
+ sizeof(tb_ekm_buf))) { |
+ return ERR_FAILED; |
+ } |
+ out->resize(sig_len); |
+ |
+ tb_signed_ekm_map_.Put(raw_public_key, *out); |
+ return OK; |
+} |
+ |
SSLFailureState SSLClientSocketOpenSSL::GetSSLFailureState() const { |
return ssl_failure_state_; |
} |