Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(800)

Unified Diff: net/socket/ssl_client_socket_openssl.cc

Issue 1378613004: Set Token-Binding HTTP header (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@tb-tls-ext-new
Patch Set: rebase Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 bcf23eaf9c63c1411a4d982b13035e1bcc484b67..774b41666cec20be23be7b180d81b8fb18b2bb4b 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -521,8 +521,129 @@ int SSLClientSocketOpenSSL::ExportKeyingMaterial(
}
int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
- NOTIMPLEMENTED();
- return ERR_NOT_IMPLEMENTED;
+ uint8_t buf[64];
+ size_t len;
+ if (!SSL_get_tls_unique(ssl_, buf, &len, arraysize(buf)))
+ return ERR_FAILED;
+ out->assign(reinterpret_cast<char*>(buf), len);
+ return OK;
+}
+
+// BuildProvidedTokenBindingID builds the serialized TokenBindingID struct as
+// defined in draft-ietf-tokbind-protocol-02. It only builds provided token
+// bindings, and only supports ECDSA P256 keys. The TokenBindingID struct
+// definition (and related structs and enums) is provided below.
+//
+// enum {
+// rsa2048_pkcs1.5_sha256(0),
+// rsa2048_pss_sha256(1),
+// ecdsap256_sha256(2), (255)
+// } TokenBindingKeyParameters;
+//
+// enum {
+// secp256r1 (23), (0xFFFF)
+// } NamedCurve;
+//
+// struct {
+// opaque point <1..2^8-1>;
+// } ECPoint;
+//
+// struct {
+// NamedCurve namedcurve;
+// ECPoint point; // Uncompressed format
+// } ECDSAParams;
+//
+// enum {
+// provided_token_binding(0), referred_token_binding(1), (255)
+// } TokenBindingType;
+//
+// struct {
+// TokenBindingType tokenbinding_type;
+// TokenBindingKeyParameters key_parameters;
+// select (key_parameters) {
+// case rsa2048_pkcs1.5_sha256:
+// case rsa2048_pss_sha256:
+// RSAPublicKey rsapubkey;
+// case ecdsap256_sha256:
+// ECDSAParams ecdsaparams;
+// }
+// } TokenBindingID;
+bool BuildProvidedTokenBindingID(crypto::ECPrivateKey* key, CBB* out) {
+ CBB ec_point;
+ if (!CBB_add_u8(out, 0) || // provided_token_binding(0)
+ !CBB_add_u8(out, TB_PARAM_ECDSAP256_SHA256) ||
+ !CBB_add_u16(out, 23) || // NamedCurve secp256r1(23)
+ !CBB_add_u8_length_prefixed(out, &ec_point)) {
+ return false;
+ }
+ std::string raw_key;
+ if (!key->ExportRawPublicKey(&raw_key)) {
+ return false;
+ }
+ if (!CBB_add_bytes(&ec_point, reinterpret_cast<uint8*>(
+ const_cast<char*>(raw_key.data())),
+ raw_key.size()) ||
+ !CBB_flush(out)) {
+ return false;
+ }
+ return true;
+}
+
+int SSLClientSocketOpenSSL::BuildProvidedTokenBinding() {
+ size_t tb_ekm_size = 32;
+ uint8_t tb_ekm_buf[32];
+ const char tb_ekm_label[] = "EXPORTER-Token-Binding";
+ // The EKM label does not include a null terminating byte. Calling arraysize
+ // on a char array includes the null terminator in the length, so subtract 1
+ // to account for that.
+ size_t ekm_label_length = arraysize(tb_ekm_label) - 1;
+ if (!SSL_export_keying_material(ssl_, tb_ekm_buf, tb_ekm_size, tb_ekm_label,
+ ekm_label_length, nullptr, 0, false)) {
+ return ERR_FAILED;
+ }
+
+ crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
+ size_t sig_len;
+ if (!EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr,
+ channel_id_key_->key()) ||
+ !EVP_DigestSignUpdate(ctx.get(), tb_ekm_buf, tb_ekm_size) ||
+ !EVP_DigestSignFinal(ctx.get(), nullptr, &sig_len)) {
+ return ERR_FAILED;
+ }
+ std::vector<uint8> signature;
+ signature.resize(sig_len);
+ if (!EVP_DigestSignFinal(ctx.get(), &signature.front(), &sig_len))
+ return ERR_FAILED;
+
+ // Build in |token_binding| the serialization of the TokenBinding struct,
+ // defined as follows:
+ //
+ // struct {
+ // TokenBindingID tokenbindingid;
+ // opaque signature<0..2^16-1>;// Signature over the exported keying
+ // material value
+ // Extension extensions<0..2^16-1>;
+ // } TokenBinding;
+ CBB token_binding;
+ uint8_t* out_data;
+ size_t out_len;
+ if (!CBB_init(&token_binding, 0) ||
+ !BuildProvidedTokenBindingID(channel_id_key_.get(), &token_binding) ||
+ !CBB_add_u16(&token_binding, sig_len) ||
+ !CBB_add_bytes(&token_binding, &signature.front(), sig_len) ||
+ // 0-length extensions
+ !CBB_add_u16(&token_binding, 0) ||
+ !CBB_finish(&token_binding, &out_data, &out_len)) {
+ CBB_cleanup(&token_binding);
+ return ERR_FAILED;
+ }
+ provided_token_binding_.assign(reinterpret_cast<char*>(out_data), out_len);
+ OPENSSL_free(out_data);
+ return OK;
+}
+
+std::string SSLClientSocketOpenSSL::GetProvidedTokenBinding() {
+ return provided_token_binding_;
}
int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
@@ -1114,16 +1235,19 @@ int SSLClientSocketOpenSSL::DoHandshakeComplete(int result) {
return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION;
}
- // Check that if token binding was negotiated, then extended master secret
- // must also be negotiated.
- if (token_binding_extension_.WasNegotiated() &&
- !ssl_->session->extended_master_secret) {
- return ERR_SSL_PROTOCOL_ERROR;
- }
-
- if (token_binding_extension_.WasNegotiated() && !channel_id_key_) {
- GotoState(STATE_TOKEN_BINDING_LOOKUP);
- return OK;
+ if (token_binding_extension_.WasNegotiated()) {
+ // Check that if token binding was negotiated, then extended master secret
+ // must also be negotiated.
+ if (!ssl_->session->extended_master_secret)
+ return ERR_SSL_PROTOCOL_ERROR;
+ if (!channel_id_key_) {
+ GotoState(STATE_TOKEN_BINDING_LOOKUP);
+ return OK;
+ }
+ if (BuildProvidedTokenBinding() != OK) {
+ NOTREACHED();
+ return ERR_FAILED;
+ }
}
// SSL handshake is completed. If NPN wasn't negotiated, see if ALPN was.
@@ -2245,9 +2369,9 @@ void SSLClientSocketOpenSSL::TokenBindingExtension::SetParams(
bool SSLClientSocketOpenSSL::TokenBindingExtension::RegisterCallbacks(
SSL_CTX* ssl_ctx) {
return SSL_CTX_add_client_custom_ext(
- ssl_ctx, kExtNum, &TokenBindingExtension::ClientAddCallback,
- &TokenBindingExtension::ClientFreeCallback, nullptr,
- &TokenBindingExtension::ClientParseCallback, nullptr);
+ ssl_ctx, kExtNum, &TokenBindingExtension::ClientAddCallback,
+ &TokenBindingExtension::ClientFreeCallback, nullptr,
+ &TokenBindingExtension::ClientParseCallback, nullptr) != 0;
mattm 2015/10/01 01:53:01 should this change be in the parent CL?
nharper 2015/10/01 20:25:46 Done.
}
int SSLClientSocketOpenSSL::TokenBindingExtension::ClientAdd(

Powered by Google App Engine
This is Rietveld 408576698