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

Side by Side 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, 2 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // OpenSSL binding for SSLClientSocket. The class layout and general principle 5 // OpenSSL binding for SSLClientSocket. The class layout and general principle
6 // of operation is derived from SSLClientSocketNSS. 6 // of operation is derived from SSLClientSocketNSS.
7 7
8 #include "net/socket/ssl_client_socket_openssl.h" 8 #include "net/socket/ssl_client_socket_openssl.h"
9 9
10 #include <errno.h> 10 #include <errno.h>
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 int ssl_error = SSL_get_error(ssl_, rv); 514 int ssl_error = SSL_get_error(ssl_, rv);
515 LOG(ERROR) << "Failed to export keying material;" 515 LOG(ERROR) << "Failed to export keying material;"
516 << " returned " << rv 516 << " returned " << rv
517 << ", SSL error code " << ssl_error; 517 << ", SSL error code " << ssl_error;
518 return MapOpenSSLError(ssl_error, err_tracer); 518 return MapOpenSSLError(ssl_error, err_tracer);
519 } 519 }
520 return OK; 520 return OK;
521 } 521 }
522 522
523 int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) { 523 int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
524 NOTIMPLEMENTED(); 524 uint8_t buf[64];
525 return ERR_NOT_IMPLEMENTED; 525 size_t len;
526 if (!SSL_get_tls_unique(ssl_, buf, &len, arraysize(buf)))
527 return ERR_FAILED;
528 out->assign(reinterpret_cast<char*>(buf), len);
529 return OK;
530 }
531
532 // BuildProvidedTokenBindingID builds the serialized TokenBindingID struct as
533 // defined in draft-ietf-tokbind-protocol-02. It only builds provided token
534 // bindings, and only supports ECDSA P256 keys. The TokenBindingID struct
535 // definition (and related structs and enums) is provided below.
536 //
537 // enum {
538 // rsa2048_pkcs1.5_sha256(0),
539 // rsa2048_pss_sha256(1),
540 // ecdsap256_sha256(2), (255)
541 // } TokenBindingKeyParameters;
542 //
543 // enum {
544 // secp256r1 (23), (0xFFFF)
545 // } NamedCurve;
546 //
547 // struct {
548 // opaque point <1..2^8-1>;
549 // } ECPoint;
550 //
551 // struct {
552 // NamedCurve namedcurve;
553 // ECPoint point; // Uncompressed format
554 // } ECDSAParams;
555 //
556 // enum {
557 // provided_token_binding(0), referred_token_binding(1), (255)
558 // } TokenBindingType;
559 //
560 // struct {
561 // TokenBindingType tokenbinding_type;
562 // TokenBindingKeyParameters key_parameters;
563 // select (key_parameters) {
564 // case rsa2048_pkcs1.5_sha256:
565 // case rsa2048_pss_sha256:
566 // RSAPublicKey rsapubkey;
567 // case ecdsap256_sha256:
568 // ECDSAParams ecdsaparams;
569 // }
570 // } TokenBindingID;
571 bool BuildProvidedTokenBindingID(crypto::ECPrivateKey* key, CBB* out) {
572 CBB ec_point;
573 if (!CBB_add_u8(out, 0) || // provided_token_binding(0)
574 !CBB_add_u8(out, TB_PARAM_ECDSAP256_SHA256) ||
575 !CBB_add_u16(out, 23) || // NamedCurve secp256r1(23)
576 !CBB_add_u8_length_prefixed(out, &ec_point)) {
577 return false;
578 }
579 std::string raw_key;
580 if (!key->ExportRawPublicKey(&raw_key)) {
581 return false;
582 }
583 if (!CBB_add_bytes(&ec_point, reinterpret_cast<uint8*>(
584 const_cast<char*>(raw_key.data())),
585 raw_key.size()) ||
586 !CBB_flush(out)) {
587 return false;
588 }
589 return true;
590 }
591
592 int SSLClientSocketOpenSSL::BuildProvidedTokenBinding() {
593 size_t tb_ekm_size = 32;
594 uint8_t tb_ekm_buf[32];
595 const char tb_ekm_label[] = "EXPORTER-Token-Binding";
596 // The EKM label does not include a null terminating byte. Calling arraysize
597 // on a char array includes the null terminator in the length, so subtract 1
598 // to account for that.
599 size_t ekm_label_length = arraysize(tb_ekm_label) - 1;
600 if (!SSL_export_keying_material(ssl_, tb_ekm_buf, tb_ekm_size, tb_ekm_label,
601 ekm_label_length, nullptr, 0, false)) {
602 return ERR_FAILED;
603 }
604
605 crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
606 size_t sig_len;
607 if (!EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr,
608 channel_id_key_->key()) ||
609 !EVP_DigestSignUpdate(ctx.get(), tb_ekm_buf, tb_ekm_size) ||
610 !EVP_DigestSignFinal(ctx.get(), nullptr, &sig_len)) {
611 return ERR_FAILED;
612 }
613 std::vector<uint8> signature;
614 signature.resize(sig_len);
615 if (!EVP_DigestSignFinal(ctx.get(), &signature.front(), &sig_len))
616 return ERR_FAILED;
617
618 // Build in |token_binding| the serialization of the TokenBinding struct,
619 // defined as follows:
620 //
621 // struct {
622 // TokenBindingID tokenbindingid;
623 // opaque signature<0..2^16-1>;// Signature over the exported keying
624 // material value
625 // Extension extensions<0..2^16-1>;
626 // } TokenBinding;
627 CBB token_binding;
628 uint8_t* out_data;
629 size_t out_len;
630 if (!CBB_init(&token_binding, 0) ||
631 !BuildProvidedTokenBindingID(channel_id_key_.get(), &token_binding) ||
632 !CBB_add_u16(&token_binding, sig_len) ||
633 !CBB_add_bytes(&token_binding, &signature.front(), sig_len) ||
634 // 0-length extensions
635 !CBB_add_u16(&token_binding, 0) ||
636 !CBB_finish(&token_binding, &out_data, &out_len)) {
637 CBB_cleanup(&token_binding);
638 return ERR_FAILED;
639 }
640 provided_token_binding_.assign(reinterpret_cast<char*>(out_data), out_len);
641 OPENSSL_free(out_data);
642 return OK;
643 }
644
645 std::string SSLClientSocketOpenSSL::GetProvidedTokenBinding() {
646 return provided_token_binding_;
526 } 647 }
527 648
528 int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) { 649 int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
529 // It is an error to create an SSLClientSocket whose context has no 650 // It is an error to create an SSLClientSocket whose context has no
530 // TransportSecurityState. 651 // TransportSecurityState.
531 DCHECK(transport_security_state_); 652 DCHECK(transport_security_state_);
532 653
533 // Although StreamSocket does allow calling Connect() after Disconnect(), 654 // Although StreamSocket does allow calling Connect() after Disconnect(),
534 // this has never worked for layered sockets. CHECK to detect any consumers 655 // this has never worked for layered sockets. CHECK to detect any consumers
535 // reconnecting an SSL socket. 656 // reconnecting an SSL socket.
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 1228
1108 int SSLClientSocketOpenSSL::DoHandshakeComplete(int result) { 1229 int SSLClientSocketOpenSSL::DoHandshakeComplete(int result) {
1109 if (result < 0) 1230 if (result < 0)
1110 return result; 1231 return result;
1111 1232
1112 if (ssl_config_.version_fallback && 1233 if (ssl_config_.version_fallback &&
1113 ssl_config_.version_max < ssl_config_.version_fallback_min) { 1234 ssl_config_.version_max < ssl_config_.version_fallback_min) {
1114 return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION; 1235 return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION;
1115 } 1236 }
1116 1237
1117 // Check that if token binding was negotiated, then extended master secret 1238 if (token_binding_extension_.WasNegotiated()) {
1118 // must also be negotiated. 1239 // Check that if token binding was negotiated, then extended master secret
1119 if (token_binding_extension_.WasNegotiated() && 1240 // must also be negotiated.
1120 !ssl_->session->extended_master_secret) { 1241 if (!ssl_->session->extended_master_secret)
1121 return ERR_SSL_PROTOCOL_ERROR; 1242 return ERR_SSL_PROTOCOL_ERROR;
1122 } 1243 if (!channel_id_key_) {
1123 1244 GotoState(STATE_TOKEN_BINDING_LOOKUP);
1124 if (token_binding_extension_.WasNegotiated() && !channel_id_key_) { 1245 return OK;
1125 GotoState(STATE_TOKEN_BINDING_LOOKUP); 1246 }
1126 return OK; 1247 if (BuildProvidedTokenBinding() != OK) {
1248 NOTREACHED();
1249 return ERR_FAILED;
1250 }
1127 } 1251 }
1128 1252
1129 // SSL handshake is completed. If NPN wasn't negotiated, see if ALPN was. 1253 // SSL handshake is completed. If NPN wasn't negotiated, see if ALPN was.
1130 if (npn_status_ == kNextProtoUnsupported) { 1254 if (npn_status_ == kNextProtoUnsupported) {
1131 const uint8_t* alpn_proto = NULL; 1255 const uint8_t* alpn_proto = NULL;
1132 unsigned alpn_len = 0; 1256 unsigned alpn_len = 0;
1133 SSL_get0_alpn_selected(ssl_, &alpn_proto, &alpn_len); 1257 SSL_get0_alpn_selected(ssl_, &alpn_proto, &alpn_len);
1134 if (alpn_len > 0) { 1258 if (alpn_len > 0) {
1135 npn_proto_.assign(reinterpret_cast<const char*>(alpn_proto), alpn_len); 1259 npn_proto_.assign(reinterpret_cast<const char*>(alpn_proto), alpn_len);
1136 npn_status_ = kNextProtoNegotiated; 1260 npn_status_ = kNextProtoNegotiated;
(...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2238 supported_params_.clear(); 2362 supported_params_.clear();
2239 for (TokenBindingParam param : params) { 2363 for (TokenBindingParam param : params) {
2240 supported_params_.push_back(param); 2364 supported_params_.push_back(param);
2241 } 2365 }
2242 }; 2366 };
2243 2367
2244 // static 2368 // static
2245 bool SSLClientSocketOpenSSL::TokenBindingExtension::RegisterCallbacks( 2369 bool SSLClientSocketOpenSSL::TokenBindingExtension::RegisterCallbacks(
2246 SSL_CTX* ssl_ctx) { 2370 SSL_CTX* ssl_ctx) {
2247 return SSL_CTX_add_client_custom_ext( 2371 return SSL_CTX_add_client_custom_ext(
2248 ssl_ctx, kExtNum, &TokenBindingExtension::ClientAddCallback, 2372 ssl_ctx, kExtNum, &TokenBindingExtension::ClientAddCallback,
2249 &TokenBindingExtension::ClientFreeCallback, nullptr, 2373 &TokenBindingExtension::ClientFreeCallback, nullptr,
2250 &TokenBindingExtension::ClientParseCallback, nullptr); 2374 &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.
2251 } 2375 }
2252 2376
2253 int SSLClientSocketOpenSSL::TokenBindingExtension::ClientAdd( 2377 int SSLClientSocketOpenSSL::TokenBindingExtension::ClientAdd(
2254 const uint8_t** out, 2378 const uint8_t** out,
2255 size_t* out_len, 2379 size_t* out_len,
2256 int* out_alert_value) { 2380 int* out_alert_value) {
2257 if (supported_params_.empty()) { 2381 if (supported_params_.empty()) {
2258 return 0; 2382 return 0;
2259 } 2383 }
2260 CBB output, parameters_list; 2384 CBB output, parameters_list;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
2373 void* parse_arg) { 2497 void* parse_arg) {
2374 DCHECK(extension_value == kExtNum); 2498 DCHECK(extension_value == kExtNum);
2375 SSLClientSocketOpenSSL* socket = 2499 SSLClientSocketOpenSSL* socket =
2376 SSLClientSocketOpenSSL::SSLContext::GetInstance()->GetClientSocketFromSSL( 2500 SSLClientSocketOpenSSL::SSLContext::GetInstance()->GetClientSocketFromSSL(
2377 ssl); 2501 ssl);
2378 return socket->token_binding_extension_.ClientParse(contents, contents_len, 2502 return socket->token_binding_extension_.ClientParse(contents, contents_len,
2379 out_alert_value); 2503 out_alert_value);
2380 } 2504 }
2381 2505
2382 } // namespace net 2506 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698