OLD | NEW |
(Empty) | |
| 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_ap
i.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 } |
OLD | NEW |