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"
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"
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
) {
30 // Import the key structure.
31 scoped_ptr
<crypto::SymmetricKey
> key(
32 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES
, raw_key
));
37 std::string
iv(raw_key
.size(), ' ');
38 crypto::Encryptor encryptor
;
39 if (!encryptor
.Init(key
.get(), crypto::Encryptor::CBC
, iv
))
43 if (!encryptor
.Decrypt(wrapped_secret
, &secret
))
49 void DefaultAuthAttemptFinalizedHandler(
50 EasyUnlockAuthAttempt::Type auth_attempt_type
,
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())
58 switch (auth_attempt_type
) {
59 case EasyUnlockAuthAttempt::TYPE_UNLOCK
:
61 proximity_auth::ScreenlockBridge::Get()->lock_handler()->Unlock(
64 proximity_auth::ScreenlockBridge::Get()->lock_handler()->EnableInput();
67 case EasyUnlockAuthAttempt::TYPE_SIGNIN
:
69 proximity_auth::ScreenlockBridge::Get()
71 ->AttemptEasySignin(user_id
, key_secret
, key_label
);
73 // Attempting signin with an empty secret is equivalent to canceling the
75 proximity_auth::ScreenlockBridge::Get()
77 ->AttemptEasySignin(user_id
, std::string(), std::string());
85 EasyUnlockAuthAttempt::EasyUnlockAuthAttempt(
86 EasyUnlockAppManager
* app_manager
,
87 const std::string
& user_id
,
89 const FinalizedCallback
& finalized_callback
)
90 : app_manager_(app_manager
),
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
)
104 bool EasyUnlockAuthAttempt::Start() {
105 DCHECK_EQ(STATE_IDLE
, state_
);
107 if (!proximity_auth::ScreenlockBridge::Get()->IsLocked())
110 proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type
=
111 proximity_auth::ScreenlockBridge::Get()->lock_handler()->GetAuthType(
114 if (auth_type
!= proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK
) {
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
)) {
137 void EasyUnlockAuthAttempt::FinalizeUnlock(const std::string
& user_id
,
139 if (state_
!= STATE_RUNNING
|| user_id
!= user_id_
)
142 if (!proximity_auth::ScreenlockBridge::Get()->IsLocked())
145 if (type_
!= TYPE_UNLOCK
) {
150 finalized_callback_
.Run(type_
, success
, user_id
, std::string(),
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_
)
161 if (!proximity_auth::ScreenlockBridge::Get()->IsLocked())
164 if (type_
!= TYPE_SIGNIN
) {
169 if (wrapped_secret
.empty()) {
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
,
187 void EasyUnlockAuthAttempt::Cancel(const std::string
& user_id
) {
190 const bool kFailure
= false;
191 finalized_callback_
.Run(type_
, kFailure
, user_id
, std::string(),