| Index: chrome/browser/signin/easy_unlock_auth_attempt.cc
|
| diff --git a/chrome/browser/signin/easy_unlock_auth_attempt.cc b/chrome/browser/signin/easy_unlock_auth_attempt.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..49b6951338858977598c164c611e5faa47590962
|
| --- /dev/null
|
| +++ b/chrome/browser/signin/easy_unlock_auth_attempt.cc
|
| @@ -0,0 +1,160 @@
|
| +// Copyright 2014 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 "chrome/browser/signin/easy_unlock_auth_attempt.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/signin/screenlock_bridge.h"
|
| +#include "crypto/encryptor.h"
|
| +#include "crypto/symmetric_key.h"
|
| +
|
| +
|
| +#if defined(OS_CHROMEOS)
|
| +#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
|
| +#endif
|
| +
|
| +namespace {
|
| +
|
| +// Fake secret used to force invalid login.
|
| +const char kStubSecret[] = "\xFF\x00";
|
| +
|
| +// Decrypts the secret that should be used to login from |wrapped_secret| using
|
| +// raw AES key |raw_key|.
|
| +// In a case of error, an empty string is returned.
|
| +std::string UnwrapSecret(const std::string& wrapped_secret,
|
| + const std::string& raw_key) {
|
| + if (raw_key.empty())
|
| + return std::string();
|
| +
|
| + // Import the key structure.
|
| + scoped_ptr<crypto::SymmetricKey> key(
|
| + crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key));
|
| +
|
| + if (!key)
|
| + return std::string();
|
| +
|
| + std::string iv(raw_key.size(), ' ');
|
| + crypto::Encryptor encryptor;
|
| + if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, iv))
|
| + return std::string();
|
| +
|
| + std::string secret;
|
| + if (!encryptor.Decrypt(wrapped_secret, &secret))
|
| + return std::string();
|
| +
|
| + return secret;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +EasyUnlockAuthAttempt::EasyUnlockAuthAttempt(Profile* profile,
|
| + const std::string& user_id,
|
| + Type type)
|
| + : profile_(profile),
|
| + state_(STATE_IDLE),
|
| + user_id_(user_id),
|
| + type_(type) {
|
| +}
|
| +
|
| +EasyUnlockAuthAttempt::~EasyUnlockAuthAttempt() {
|
| + if (state_ == STATE_RUNNING)
|
| + Cancel(user_id_);
|
| +}
|
| +
|
| +bool EasyUnlockAuthAttempt::Start(const std::string& user_id) {
|
| + DCHECK(state_ == STATE_IDLE);
|
| +
|
| + if (!ScreenlockBridge::Get()->IsLocked())
|
| + return false;
|
| +
|
| + if (user_id != user_id_) {
|
| + Cancel(user_id);
|
| + return false;
|
| + }
|
| +
|
| + ScreenlockBridge::LockHandler::AuthType auth_type =
|
| + ScreenlockBridge::Get()->lock_handler()->GetAuthType(user_id);
|
| +
|
| + if (auth_type != ScreenlockBridge::LockHandler::USER_CLICK) {
|
| + Cancel(user_id);
|
| + return false;
|
| + }
|
| +
|
| + state_ = STATE_RUNNING;
|
| +
|
| + // TODO(tbarzic): Replace this with an easyUnlockPrivate event that will
|
| + // report more context to the app (e.g. user id, whether the attempt is for
|
| + // signin or unlock).
|
| + extensions::ScreenlockPrivateEventRouter* router =
|
| + extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
|
| + profile_);
|
| + return router->OnAuthAttempted(auth_type, "");
|
| +}
|
| +
|
| +void EasyUnlockAuthAttempt::FinalizeUnlock(const std::string& user_id,
|
| + bool success) {
|
| + if (state_ != STATE_RUNNING || user_id != user_id_)
|
| + return;
|
| +
|
| + if (type_ != TYPE_UNLOCK) {
|
| + Cancel(user_id_);
|
| + return;
|
| + }
|
| +
|
| + if (!ScreenlockBridge::Get()->IsLocked())
|
| + return;
|
| +
|
| + if (success) {
|
| + ScreenlockBridge::Get()->lock_handler()->Unlock(user_id_);
|
| + } else {
|
| + ScreenlockBridge::Get()->lock_handler()->EnableInput();
|
| + }
|
| +
|
| + state_ = STATE_DONE;
|
| +}
|
| +
|
| +void EasyUnlockAuthAttempt::FinalizeSignin(const std::string& user_id,
|
| + const std::string& wrapped_secret,
|
| + const std::string& raw_session_key) {
|
| + if (state_ != STATE_RUNNING || user_id != user_id_)
|
| + return;
|
| +
|
| + if (type_ != TYPE_SIGNIN) {
|
| + Cancel(user_id_);
|
| + return;
|
| + }
|
| +
|
| + if (!ScreenlockBridge::Get()->IsLocked())
|
| + return;
|
| +
|
| +
|
| + std::string unwrapped_secret = UnwrapSecret(wrapped_secret, raw_session_key);
|
| +
|
| + // If secret is not set, set it to an arbitrary value, otherwise there will
|
| + // be no authenitcation attempt and the ui will get stuck.
|
| + // TODO(tbarzic): Find a better way to handle this case.
|
| + if (unwrapped_secret.empty())
|
| + unwrapped_secret = kStubSecret;
|
| +
|
| + std::string key_label;
|
| +#if defined(OS_CHROMEOS)
|
| + key_label = chromeos::EasyUnlockKeyManager::GetKeyLabel(0u);
|
| +#endif // defined(OS_CHROMEOS)
|
| +
|
| + ScreenlockBridge::Get()->lock_handler()->AttemptUserClickLogin(
|
| + user_id,
|
| + unwrapped_secret,
|
| + key_label);
|
| + state_ = STATE_DONE;
|
| +}
|
| +
|
| +void EasyUnlockAuthAttempt::Cancel(const std::string& user_id) {
|
| + if (type_ == TYPE_UNLOCK)
|
| + FinalizeUnlock(user_id, false);
|
| + else
|
| + FinalizeSignin(user_id, "", "");
|
| + state_ = STATE_DONE;
|
| +}
|
|
|