Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / signin / easy_unlock_auth_attempt.cc
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.
4
5 #include "chrome/browser/signin/easy_unlock_auth_attempt.h"
6
7 #include "base/logging.h"
8 #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/signin/screenlock_bridge.h"
11 #include "crypto/encryptor.h"
12 #include "crypto/symmetric_key.h"
13
14
15 #if defined(OS_CHROMEOS)
16 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
17 #endif
18
19 namespace {
20
21 // Fake secret used to force invalid login.
22 const char kStubSecret[] = "\xFF\x00";
23
24 // Decrypts the secret that should be used to login from |wrapped_secret| using
25 // raw AES key |raw_key|.
26 // In a case of error, an empty string is returned.
27 std::string UnwrapSecret(const std::string& wrapped_secret,
28                          const std::string& raw_key) {
29   if (raw_key.empty())
30     return std::string();
31
32   // Import the key structure.
33   scoped_ptr<crypto::SymmetricKey> key(
34      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key));
35
36   if (!key)
37     return std::string();
38
39   std::string iv(raw_key.size(), ' ');
40   crypto::Encryptor encryptor;
41   if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, iv))
42     return std::string();
43
44   std::string secret;
45   if (!encryptor.Decrypt(wrapped_secret, &secret))
46     return std::string();
47
48   return secret;
49 }
50
51 }  // namespace
52
53 EasyUnlockAuthAttempt::EasyUnlockAuthAttempt(Profile* profile,
54                                              const std::string& user_id,
55                                              Type type)
56     : profile_(profile),
57       state_(STATE_IDLE),
58       user_id_(user_id),
59       type_(type) {
60 }
61
62 EasyUnlockAuthAttempt::~EasyUnlockAuthAttempt() {
63   if (state_ == STATE_RUNNING)
64     Cancel(user_id_);
65 }
66
67 bool EasyUnlockAuthAttempt::Start(const std::string& user_id) {
68   DCHECK(state_ == STATE_IDLE);
69
70   if (!ScreenlockBridge::Get()->IsLocked())
71     return false;
72
73   if (user_id != user_id_) {
74     Cancel(user_id);
75     return false;
76   }
77
78   ScreenlockBridge::LockHandler::AuthType auth_type =
79       ScreenlockBridge::Get()->lock_handler()->GetAuthType(user_id);
80
81   if (auth_type != ScreenlockBridge::LockHandler::USER_CLICK) {
82     Cancel(user_id);
83     return false;
84   }
85
86   state_ = STATE_RUNNING;
87
88   // TODO(tbarzic): Replace this with an easyUnlockPrivate event that will
89   // report more context to the app (e.g. user id, whether the attempt is for
90   // signin or unlock).
91   extensions::ScreenlockPrivateEventRouter* router =
92       extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get(
93           profile_);
94   return router->OnAuthAttempted(auth_type, "");
95 }
96
97 void EasyUnlockAuthAttempt::FinalizeUnlock(const std::string& user_id,
98                                            bool success) {
99   if (state_ != STATE_RUNNING || user_id != user_id_)
100     return;
101
102   if (type_ != TYPE_UNLOCK) {
103     Cancel(user_id_);
104     return;
105   }
106
107   if (!ScreenlockBridge::Get()->IsLocked())
108     return;
109
110   if (success) {
111     ScreenlockBridge::Get()->lock_handler()->Unlock(user_id_);
112   } else {
113     ScreenlockBridge::Get()->lock_handler()->EnableInput();
114   }
115
116   state_ = STATE_DONE;
117 }
118
119 void EasyUnlockAuthAttempt::FinalizeSignin(const std::string& user_id,
120                                            const std::string& wrapped_secret,
121                                            const std::string& raw_session_key) {
122   if (state_ != STATE_RUNNING || user_id != user_id_)
123     return;
124
125   if (type_ != TYPE_SIGNIN) {
126     Cancel(user_id_);
127     return;
128   }
129
130   if (!ScreenlockBridge::Get()->IsLocked())
131     return;
132
133
134   std::string unwrapped_secret = UnwrapSecret(wrapped_secret, raw_session_key);
135
136   // If secret is not set, set it to an arbitrary value, otherwise there will
137   // be no authenitcation attempt and the ui will get stuck.
138   // TODO(tbarzic): Find a better way to handle this case.
139   if (unwrapped_secret.empty())
140     unwrapped_secret = kStubSecret;
141
142   std::string key_label;
143 #if defined(OS_CHROMEOS)
144   key_label = chromeos::EasyUnlockKeyManager::GetKeyLabel(0u);
145 #endif  // defined(OS_CHROMEOS)
146
147   ScreenlockBridge::Get()->lock_handler()->AttemptEasySignin(
148       user_id,
149       unwrapped_secret,
150       key_label);
151   state_ = STATE_DONE;
152 }
153
154 void EasyUnlockAuthAttempt::Cancel(const std::string& user_id) {
155   if (type_ == TYPE_UNLOCK)
156     FinalizeUnlock(user_id, false);
157   else
158     FinalizeSignin(user_id, "", "");
159   state_ = STATE_DONE;
160 }