MD Downloads: UI review feedback
[chromium-blink-merge.git] / chrome / browser / signin / easy_unlock_auth_attempt.cc
blob9b82890ce93d815b901065c7efcdf6ee19b42990
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/signin/easy_unlock_auth_attempt.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "chrome/browser/signin/easy_unlock_app_manager.h"
11 #include "components/proximity_auth/screenlock_bridge.h"
12 #include "components/proximity_auth/switches.h"
13 #include "crypto/encryptor.h"
14 #include "crypto/symmetric_key.h"
16 #if defined(OS_CHROMEOS)
17 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
18 #endif
20 namespace {
22 // Decrypts the secret that should be used to login from |wrapped_secret| using
23 // raw AES key |raw_key|.
24 // In a case of error, an empty string is returned.
25 std::string UnwrapSecret(const std::string& wrapped_secret,
26 const std::string& raw_key) {
27 if (raw_key.empty())
28 return std::string();
30 // Import the key structure.
31 scoped_ptr<crypto::SymmetricKey> key(
32 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key));
34 if (!key)
35 return std::string();
37 std::string iv(raw_key.size(), ' ');
38 crypto::Encryptor encryptor;
39 if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, iv))
40 return std::string();
42 std::string secret;
43 if (!encryptor.Decrypt(wrapped_secret, &secret))
44 return std::string();
46 return secret;
49 void DefaultAuthAttemptFinalizedHandler(
50 EasyUnlockAuthAttempt::Type auth_attempt_type,
51 bool success,
52 const std::string& user_id,
53 const std::string& key_secret,
54 const std::string& key_label) {
55 if (!proximity_auth::ScreenlockBridge::Get()->IsLocked())
56 return;
58 switch (auth_attempt_type) {
59 case EasyUnlockAuthAttempt::TYPE_UNLOCK:
60 if (success) {
61 proximity_auth::ScreenlockBridge::Get()->lock_handler()->Unlock(
62 user_id);
63 } else {
64 proximity_auth::ScreenlockBridge::Get()->lock_handler()->EnableInput();
66 return;
67 case EasyUnlockAuthAttempt::TYPE_SIGNIN:
68 if (success) {
69 proximity_auth::ScreenlockBridge::Get()
70 ->lock_handler()
71 ->AttemptEasySignin(user_id, key_secret, key_label);
72 } else {
73 // Attempting signin with an empty secret is equivalent to canceling the
74 // attempt.
75 proximity_auth::ScreenlockBridge::Get()
76 ->lock_handler()
77 ->AttemptEasySignin(user_id, std::string(), std::string());
79 return;
83 } // namespace
85 EasyUnlockAuthAttempt::EasyUnlockAuthAttempt(
86 EasyUnlockAppManager* app_manager,
87 const std::string& user_id,
88 Type type,
89 const FinalizedCallback& finalized_callback)
90 : app_manager_(app_manager),
91 state_(STATE_IDLE),
92 user_id_(user_id),
93 type_(type),
94 finalized_callback_(finalized_callback) {
95 if (finalized_callback_.is_null())
96 finalized_callback_ = base::Bind(&DefaultAuthAttemptFinalizedHandler);
99 EasyUnlockAuthAttempt::~EasyUnlockAuthAttempt() {
100 if (state_ == STATE_RUNNING)
101 Cancel(user_id_);
104 bool EasyUnlockAuthAttempt::Start() {
105 DCHECK_EQ(STATE_IDLE, state_);
107 if (!proximity_auth::ScreenlockBridge::Get()->IsLocked())
108 return false;
110 proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type =
111 proximity_auth::ScreenlockBridge::Get()->lock_handler()->GetAuthType(
112 user_id_);
114 if (auth_type != proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK) {
115 Cancel(user_id_);
116 return false;
119 state_ = STATE_RUNNING;
121 // We need this workaround for ProximityAuthBleSystem, which is already
122 // notified in EasyUnlockService. No notification is sent when only the
123 // |kEnableBluetoothLowEnergyDiscovery| flag is set, and
124 // |app_manager_->SendAuthAttemptEvent()| returns false. As a result, the auth
125 // attempt will always fail.
126 // TODO(sacomoto): Remove this when it's not needed anymore.
127 if (!app_manager_->SendAuthAttemptEvent() &&
128 !base::CommandLine::ForCurrentProcess()->HasSwitch(
129 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery)) {
130 Cancel(user_id_);
131 return false;
134 return true;
137 void EasyUnlockAuthAttempt::FinalizeUnlock(const std::string& user_id,
138 bool success) {
139 if (state_ != STATE_RUNNING || user_id != user_id_)
140 return;
142 if (!proximity_auth::ScreenlockBridge::Get()->IsLocked())
143 return;
145 if (type_ != TYPE_UNLOCK) {
146 Cancel(user_id_);
147 return;
150 finalized_callback_.Run(type_, success, user_id, std::string(),
151 std::string());
152 state_ = STATE_DONE;
155 void EasyUnlockAuthAttempt::FinalizeSignin(const std::string& user_id,
156 const std::string& wrapped_secret,
157 const std::string& raw_session_key) {
158 if (state_ != STATE_RUNNING || user_id != user_id_)
159 return;
161 if (!proximity_auth::ScreenlockBridge::Get()->IsLocked())
162 return;
164 if (type_ != TYPE_SIGNIN) {
165 Cancel(user_id_);
166 return;
169 if (wrapped_secret.empty()) {
170 Cancel(user_id_);
171 return;
174 std::string unwrapped_secret = UnwrapSecret(wrapped_secret, raw_session_key);
176 std::string key_label;
177 #if defined(OS_CHROMEOS)
178 key_label = chromeos::EasyUnlockKeyManager::GetKeyLabel(0u);
179 #endif // defined(OS_CHROMEOS)
181 const bool kSuccess = true;
182 finalized_callback_.Run(type_, kSuccess, user_id, unwrapped_secret,
183 key_label);
184 state_ = STATE_DONE;
187 void EasyUnlockAuthAttempt::Cancel(const std::string& user_id) {
188 state_ = STATE_DONE;
190 const bool kFailure = false;
191 finalized_callback_.Run(type_, kFailure, user_id, std::string(),
192 std::string());