OLD | NEW |
---|---|
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 Loading... | |
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))) | |
davidben
2015/10/15 20:37:16
Both this function and SSL_export_keying_material
| |
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 Loading... | |
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 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 |
OLD | NEW |