diff options
author | chrishall <chrishall@chromium.org> | 2016-03-09 22:47:20 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-10 06:49:39 +0000 |
commit | f1dcaac3801ed8d0a8abe62f1496e61fbaf639a7 (patch) | |
tree | f868b3d5d0d8fd4cd747e1739734f3d53fbc198d /remoting/protocol/spake2_authenticator.cc | |
parent | 3a46edeeb8cc6b47bfd3210042964324eaf28c07 (diff) | |
download | chromium_src-f1dcaac3801ed8d0a8abe62f1496e61fbaf639a7.zip chromium_src-f1dcaac3801ed8d0a8abe62f1496e61fbaf639a7.tar.gz chromium_src-f1dcaac3801ed8d0a8abe62f1496e61fbaf639a7.tar.bz2 |
Revert of Implement authenticator based on SPAKE2 implementation in boringssl. (patchset #5 id:140001 of https://codereview.chromium.org/1759313002/ )
Reason for revert:
This patch added 2 more tests which are now failing on Linux MSan Tests as of build #14316
https://build.chromium.org/p/chromium.memory.fyi/builders/Linux%20MSan%20Tests/builds/14316
Spake2AuthenticatorTest.InvalidSecret (run #1):
[ RUN ] Spake2AuthenticatorTest.InvalidSecret
==10538==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x14bb0fd in ?? third_party/modp_b64/modp_b64.cc:91:20
#1 0xdcf2f6 in Base64Encode base/base64.cc:18:24
#2 0x12d6e6c in EncodeBinaryValueToXml remoting/protocol/spake2_authenticator.cc:47:3
and
Spake2AuthenticatorTest.SuccessfulAuth (run #1):
[ RUN ] Spake2AuthenticatorTest.SuccessfulAuth
==10537==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x14bb0fd in ?? third_party/modp_b64/modp_b64.cc:91:20
#1 0xdcf2f6 in Base64Encode base/base64.cc:18:24
#2 0x12d6e6c in EncodeBinaryValueToXml remoting/protocol/spake2_authenticator.cc:47:3
Original issue's description:
> Implement authenticator based on SPAKE2 implementation in boringssl.
>
> The new authenticator uses SPAKE2 over Curve25519. It will
> be enabled in host and client in a separate CL.
>
> BUG=589698
>
> Committed: https://crrev.com/bf336334ba59ae7cd150e9cb36a9b248d174a4eb
> Cr-Commit-Position: refs/heads/master@{#379972}
TBR=kelvinp@chromium.org,davidben@chromium.org,arnarb@chromium.org,sergeyu@chromium.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=589698
Review URL: https://codereview.chromium.org/1778223003
Cr-Commit-Position: refs/heads/master@{#380365}
Diffstat (limited to 'remoting/protocol/spake2_authenticator.cc')
-rw-r--r-- | remoting/protocol/spake2_authenticator.cc | 317 |
1 files changed, 0 insertions, 317 deletions
diff --git a/remoting/protocol/spake2_authenticator.cc b/remoting/protocol/spake2_authenticator.cc deleted file mode 100644 index d7c0a6c..0000000 --- a/remoting/protocol/spake2_authenticator.cc +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/protocol/spake2_authenticator.h" - -#include <utility> - -#include "base/base64.h" -#include "base/logging.h" -#include "base/sys_byteorder.h" -#include "crypto/hmac.h" -#include "crypto/secure_util.h" -#include "remoting/base/constants.h" -#include "remoting/base/rsa_key_pair.h" -#include "remoting/protocol/ssl_hmac_channel_authenticator.h" -#include "third_party/boringssl/src/include/openssl/curve25519.h" -#include "third_party/webrtc/libjingle/xmllite/xmlelement.h" - -namespace remoting { -namespace protocol { - -namespace { - -// Each peer sends 2 messages: <spake-message> and <verification-hash>. The -// content of <spake-message> is the output of SPAKE2_generate_msg() and must -// be passed to SPAKE2_process_msg() on the other end. This is enough to -// generate authentication key. <verification-hash> is sent to confirm that both -// ends get the same authentication key (which means they both know the -// password). This verification hash is calculated in -// CalculateVerificationHash() as follows: -// HMAC_SHA256(auth_key, ("host"|"client") + local_jid.length() + local_jid + -// remote_jid.length() + remote_jid) -// where auth_key is the key produced by SPAKE2. - -const buzz::StaticQName kSpakeMessageTag = {kChromotingXmlNamespace, - "spake-message"}; -const buzz::StaticQName kVerificationHashTag = {kChromotingXmlNamespace, - "verification-hash"}; -const buzz::StaticQName kCertificateTag = {kChromotingXmlNamespace, - "certificate"}; - -scoped_ptr<buzz::XmlElement> EncodeBinaryValueToXml( - const buzz::StaticQName& qname, - const std::string& content) { - std::string content_base64; - base::Base64Encode(content, &content_base64); - - scoped_ptr<buzz::XmlElement> result(new buzz::XmlElement(qname)); - result->SetBodyText(content_base64); - return result; -} - -// Finds tag named |qname| in base_message and decodes it from base64 and stores -// in |data|. If the element is not present then found is set to false otherwise -// it's set to true. If the element is there and it's content cound't be decoded -// then false is returned. -bool DecodeBinaryValueFromXml(const buzz::XmlElement* message, - const buzz::QName& qname, - bool* found, - std::string* data) { - const buzz::XmlElement* element = message->FirstNamed(qname); - *found = element != nullptr; - if (!*found) - return true; - - if (!base::Base64Decode(element->BodyText(), data)) { - LOG(WARNING) << "Failed to parse " << qname.LocalPart(); - return false; - } - - return !data->empty(); -} - -std::string PrefixWithLength(const std::string& str) { - uint32_t length = base::HostToNet32(str.size()); - return std::string(reinterpret_cast<char*>(&length), sizeof(length)) + str; -} - -} // namespace - -// static -scoped_ptr<Authenticator> Spake2Authenticator::CreateForClient( - const std::string& local_id, - const std::string& remote_id, - const std::string& shared_secret, - Authenticator::State initial_state) { - return make_scoped_ptr(new Spake2Authenticator( - local_id, remote_id, shared_secret, false, initial_state)); -} - -// static -scoped_ptr<Authenticator> Spake2Authenticator::CreateForHost( - const std::string& local_id, - const std::string& remote_id, - const std::string& shared_secret, - const std::string& local_cert, - scoped_refptr<RsaKeyPair> key_pair, - Authenticator::State initial_state) { - scoped_ptr<Spake2Authenticator> result(new Spake2Authenticator( - local_id, remote_id, shared_secret, true, initial_state)); - result->local_cert_ = local_cert; - result->local_key_pair_ = key_pair; - return std::move(result); -} - -Spake2Authenticator::Spake2Authenticator(const std::string& local_id, - const std::string& remote_id, - const std::string& shared_secret, - bool is_host, - Authenticator::State initial_state) - : local_id_(local_id), - remote_id_(remote_id), - shared_secret_(shared_secret), - is_host_(is_host), - state_(initial_state) { - spake2_context_ = SPAKE2_CTX_new( - is_host ? spake2_role_bob : spake2_role_alice, - reinterpret_cast<const uint8_t*>(local_id_.data()), local_id_.size(), - reinterpret_cast<const uint8_t*>(remote_id_.data()), remote_id_.size()); - - // Generate first message and push it to |pending_messages_|. - uint8_t message[SPAKE2_MAX_MSG_SIZE]; - size_t message_size; - int result = SPAKE2_generate_msg( - spake2_context_, message, &message_size, sizeof(message), - reinterpret_cast<const uint8_t*>(shared_secret_.data()), - shared_secret_.size()); - CHECK(result); - local_spake_message_.assign(reinterpret_cast<char*>(message), message_size); -} - -Spake2Authenticator::~Spake2Authenticator() { - SPAKE2_CTX_free(spake2_context_); -} - -Authenticator::State Spake2Authenticator::state() const { - if (state_ == ACCEPTED && !outgoing_verification_hash_.empty()) - return MESSAGE_READY; - return state_; -} - -bool Spake2Authenticator::started() const { - return started_; -} - -Authenticator::RejectionReason Spake2Authenticator::rejection_reason() const { - DCHECK_EQ(state(), REJECTED); - return rejection_reason_; -} - -void Spake2Authenticator::ProcessMessage(const buzz::XmlElement* message, - const base::Closure& resume_callback) { - ProcessMessageInternal(message); - resume_callback.Run(); -} - -void Spake2Authenticator::ProcessMessageInternal( - const buzz::XmlElement* message) { - DCHECK_EQ(state(), WAITING_MESSAGE); - - // Parse the certificate. - bool cert_present; - if (!DecodeBinaryValueFromXml(message, kCertificateTag, &cert_present, - &remote_cert_)) { - state_ = REJECTED; - rejection_reason_ = PROTOCOL_ERROR; - return; - } - - // Client always expects certificate in the first message. - if (!is_host_ && remote_cert_.empty()) { - LOG(WARNING) << "No valid host certificate."; - state_ = REJECTED; - rejection_reason_ = PROTOCOL_ERROR; - return; - } - - bool spake_message_present = false; - std::string spake_message; - bool verification_hash_present = false; - std::string verification_hash; - if (!DecodeBinaryValueFromXml(message, kSpakeMessageTag, - &spake_message_present, &spake_message) || - !DecodeBinaryValueFromXml(message, kVerificationHashTag, - &verification_hash_present, - &verification_hash)) { - state_ = REJECTED; - rejection_reason_ = PROTOCOL_ERROR; - return; - } - - // |auth_key_| is generated when <spake-message> is received. - if (auth_key_.empty()) { - if (!spake_message_present) { - LOG(WARNING) << "<spake-message> not found."; - state_ = REJECTED; - rejection_reason_ = PROTOCOL_ERROR; - return; - } - uint8_t key[SPAKE2_MAX_KEY_SIZE]; - size_t key_size; - started_ = true; - int result = SPAKE2_process_msg( - spake2_context_, key, &key_size, sizeof(key), - reinterpret_cast<const uint8_t*>(spake_message.data()), - spake_message.size()); - if (!result) { - state_ = REJECTED; - rejection_reason_ = INVALID_CREDENTIALS; - return; - } - CHECK(key_size); - auth_key_.assign(reinterpret_cast<char*>(key), key_size); - - outgoing_verification_hash_ = - CalculateVerificationHash(is_host_, local_id_, remote_id_); - expected_verification_hash_ = - CalculateVerificationHash(!is_host_, remote_id_, local_id_); - } else if (spake_message_present) { - LOG(WARNING) << "Received duplicate <spake-message>."; - state_ = REJECTED; - rejection_reason_ = PROTOCOL_ERROR; - return; - } - - if (spake_message_sent_ && !verification_hash_present) { - LOG(WARNING) << "Didn't receive <verification-hash> when expected."; - state_ = REJECTED; - rejection_reason_ = PROTOCOL_ERROR; - return; - } - - if (verification_hash_present) { - if (verification_hash.size() != expected_verification_hash_.size() || - !crypto::SecureMemEqual(verification_hash.data(), - expected_verification_hash_.data(), - verification_hash.size())) { - state_ = REJECTED; - rejection_reason_ = INVALID_CREDENTIALS; - return; - } - state_ = ACCEPTED; - return; - } - - state_ = MESSAGE_READY; -} - -scoped_ptr<buzz::XmlElement> Spake2Authenticator::GetNextMessage() { - DCHECK_EQ(state(), MESSAGE_READY); - - scoped_ptr<buzz::XmlElement> message = CreateEmptyAuthenticatorMessage(); - - if (!spake_message_sent_) { - if (!local_cert_.empty()) { - message->AddElement( - EncodeBinaryValueToXml(kCertificateTag, local_cert_).release()); - } - - message->AddElement( - EncodeBinaryValueToXml(kSpakeMessageTag, local_spake_message_) - .release()); - - spake_message_sent_ = true; - } - - if (!outgoing_verification_hash_.empty()) { - message->AddElement(EncodeBinaryValueToXml(kVerificationHashTag, - outgoing_verification_hash_) - .release()); - outgoing_verification_hash_.clear(); - } - - if (state_ != ACCEPTED) { - state_ = WAITING_MESSAGE; - } - return message; -} - -const std::string& Spake2Authenticator::GetAuthKey() const { - return auth_key_; -} - -scoped_ptr<ChannelAuthenticator> -Spake2Authenticator::CreateChannelAuthenticator() const { - DCHECK_EQ(state(), ACCEPTED); - CHECK(!auth_key_.empty()); - - if (is_host_) { - return SslHmacChannelAuthenticator::CreateForHost( - local_cert_, local_key_pair_, auth_key_); - } else { - return SslHmacChannelAuthenticator::CreateForClient(remote_cert_, - auth_key_); - } -} - -std::string Spake2Authenticator::CalculateVerificationHash( - bool from_host, - const std::string& local_id, - const std::string& remote_id) { - std::string message = (from_host ? "host" : "client") + - PrefixWithLength(local_id) + - PrefixWithLength(remote_id); - crypto::HMAC hmac(crypto::HMAC::SHA256); - std::string result(hmac.DigestLength(), '\0'); - if (!hmac.Init(auth_key_) || - !hmac.Sign(message, reinterpret_cast<uint8_t*>(&result[0]), - result.length())) { - LOG(FATAL) << "Failed to calculate HMAC."; - } - return result; -} - -} // namespace protocol -} // namespace remoting |