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 "chromeos/login/auth/extended_authenticator_impl.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
10 #include "chromeos/cryptohome/async_method_caller.h"
11 #include "chromeos/cryptohome/cryptohome_parameters.h"
12 #include "chromeos/cryptohome/homedir_methods.h"
13 #include "chromeos/cryptohome/system_salt_getter.h"
14 #include "chromeos/dbus/cryptohome_client.h"
15 #include "chromeos/dbus/dbus_thread_manager.h"
16 #include "chromeos/login/auth/auth_status_consumer.h"
17 #include "chromeos/login/auth/key.h"
18 #include "chromeos/login/auth/user_context.h"
19 #include "chromeos/login_event_recorder.h"
20 #include "crypto/sha2.h"
21 #include "google_apis/gaia/gaia_auth_util.h"
27 void RecordStartMarker(const std::string
& marker
) {
28 std::string full_marker
= "Cryptohome-";
29 full_marker
.append(marker
);
30 full_marker
.append("-Start");
31 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker
, false);
34 void RecordEndMarker(const std::string
& marker
) {
35 std::string full_marker
= "Cryptohome-";
36 full_marker
.append(marker
);
37 full_marker
.append("-End");
38 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker
, false);
43 ExtendedAuthenticatorImpl::ExtendedAuthenticatorImpl(
44 NewAuthStatusConsumer
* consumer
)
45 : salt_obtained_(false), consumer_(consumer
), old_consumer_(NULL
) {
46 SystemSaltGetter::Get()->GetSystemSalt(
47 base::Bind(&ExtendedAuthenticatorImpl::OnSaltObtained
, this));
50 ExtendedAuthenticatorImpl::ExtendedAuthenticatorImpl(
51 AuthStatusConsumer
* consumer
)
52 : salt_obtained_(false), consumer_(NULL
), old_consumer_(consumer
) {
53 SystemSaltGetter::Get()->GetSystemSalt(
54 base::Bind(&ExtendedAuthenticatorImpl::OnSaltObtained
, this));
57 void ExtendedAuthenticatorImpl::SetConsumer(AuthStatusConsumer
* consumer
) {
58 old_consumer_
= consumer
;
61 void ExtendedAuthenticatorImpl::AuthenticateToMount(
62 const UserContext
& context
,
63 const ResultCallback
& success_callback
) {
66 base::Bind(&ExtendedAuthenticatorImpl::DoAuthenticateToMount
,
71 void ExtendedAuthenticatorImpl::AuthenticateToCheck(
72 const UserContext
& context
,
73 const base::Closure
& success_callback
) {
76 base::Bind(&ExtendedAuthenticatorImpl::DoAuthenticateToCheck
,
81 void ExtendedAuthenticatorImpl::CreateMount(
82 const std::string
& user_id
,
83 const std::vector
<cryptohome::KeyDefinition
>& keys
,
84 const ResultCallback
& success_callback
) {
85 RecordStartMarker("MountEx");
87 std::string canonicalized
= gaia::CanonicalizeEmail(user_id
);
88 cryptohome::Identification
id(canonicalized
);
89 cryptohome::Authorization
auth(keys
.front());
90 cryptohome::MountParameters
mount(false);
91 for (size_t i
= 0; i
< keys
.size(); i
++) {
92 mount
.create_keys
.push_back(keys
[i
]);
94 UserContext
context(user_id
);
95 Key
key(keys
.front().secret
);
96 key
.SetLabel(keys
.front().label
);
99 cryptohome::HomedirMethods::GetInstance()->MountEx(
103 base::Bind(&ExtendedAuthenticatorImpl::OnMountComplete
,
110 void ExtendedAuthenticatorImpl::AddKey(const UserContext
& context
,
111 const cryptohome::KeyDefinition
& key
,
112 bool replace_existing
,
113 const base::Closure
& success_callback
) {
114 TransformKeyIfNeeded(context
,
115 base::Bind(&ExtendedAuthenticatorImpl::DoAddKey
,
122 void ExtendedAuthenticatorImpl::UpdateKeyAuthorized(
123 const UserContext
& context
,
124 const cryptohome::KeyDefinition
& key
,
125 const std::string
& signature
,
126 const base::Closure
& success_callback
) {
127 TransformKeyIfNeeded(
129 base::Bind(&ExtendedAuthenticatorImpl::DoUpdateKeyAuthorized
,
136 void ExtendedAuthenticatorImpl::RemoveKey(const UserContext
& context
,
137 const std::string
& key_to_remove
,
138 const base::Closure
& success_callback
) {
139 TransformKeyIfNeeded(context
,
140 base::Bind(&ExtendedAuthenticatorImpl::DoRemoveKey
,
146 void ExtendedAuthenticatorImpl::TransformKeyIfNeeded(
147 const UserContext
& user_context
,
148 const ContextCallback
& callback
) {
149 if (user_context
.GetKey()->GetKeyType() != Key::KEY_TYPE_PASSWORD_PLAIN
) {
150 callback
.Run(user_context
);
154 if (!salt_obtained_
) {
155 system_salt_callbacks_
.push_back(
156 base::Bind(&ExtendedAuthenticatorImpl::TransformKeyIfNeeded
,
163 UserContext transformed_context
= user_context
;
164 transformed_context
.GetKey()->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF
,
166 callback
.Run(transformed_context
);
169 ExtendedAuthenticatorImpl::~ExtendedAuthenticatorImpl() {
172 void ExtendedAuthenticatorImpl::OnSaltObtained(const std::string
& system_salt
) {
173 salt_obtained_
= true;
174 system_salt_
= system_salt
;
175 for (std::vector
<base::Closure
>::const_iterator it
=
176 system_salt_callbacks_
.begin();
177 it
!= system_salt_callbacks_
.end();
181 system_salt_callbacks_
.clear();
184 void ExtendedAuthenticatorImpl::DoAuthenticateToMount(
185 const ResultCallback
& success_callback
,
186 const UserContext
& user_context
) {
187 RecordStartMarker("MountEx");
189 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
190 cryptohome::Identification
id(canonicalized
);
191 const Key
* const key
= user_context
.GetKey();
192 cryptohome::Authorization
auth(key
->GetSecret(), key
->GetLabel());
193 cryptohome::MountParameters
mount(false);
195 cryptohome::HomedirMethods::GetInstance()->MountEx(
199 base::Bind(&ExtendedAuthenticatorImpl::OnMountComplete
,
206 void ExtendedAuthenticatorImpl::DoAuthenticateToCheck(
207 const base::Closure
& success_callback
,
208 const UserContext
& user_context
) {
209 RecordStartMarker("CheckKeyEx");
211 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
212 cryptohome::Identification
id(canonicalized
);
213 const Key
* const key
= user_context
.GetKey();
214 cryptohome::Authorization
auth(key
->GetSecret(), key
->GetLabel());
216 cryptohome::HomedirMethods::GetInstance()->CheckKeyEx(
219 base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete
,
226 void ExtendedAuthenticatorImpl::DoAddKey(const cryptohome::KeyDefinition
& key
,
227 bool replace_existing
,
228 const base::Closure
& success_callback
,
229 const UserContext
& user_context
) {
230 RecordStartMarker("AddKeyEx");
232 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
233 cryptohome::Identification
id(canonicalized
);
234 const Key
* const auth_key
= user_context
.GetKey();
235 cryptohome::Authorization
auth(auth_key
->GetSecret(), auth_key
->GetLabel());
237 cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
242 base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete
,
249 void ExtendedAuthenticatorImpl::DoUpdateKeyAuthorized(
250 const cryptohome::KeyDefinition
& key
,
251 const std::string
& signature
,
252 const base::Closure
& success_callback
,
253 const UserContext
& user_context
) {
254 RecordStartMarker("UpdateKeyAuthorized");
256 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
257 cryptohome::Identification
id(canonicalized
);
258 const Key
* const auth_key
= user_context
.GetKey();
259 cryptohome::Authorization
auth(auth_key
->GetSecret(), auth_key
->GetLabel());
261 cryptohome::HomedirMethods::GetInstance()->UpdateKeyEx(
266 base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete
,
268 "UpdateKeyAuthorized",
273 void ExtendedAuthenticatorImpl::DoRemoveKey(const std::string
& key_to_remove
,
274 const base::Closure
& success_callback
,
275 const UserContext
& user_context
) {
276 RecordStartMarker("RemoveKeyEx");
278 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
279 cryptohome::Identification
id(canonicalized
);
280 const Key
* const auth_key
= user_context
.GetKey();
281 cryptohome::Authorization
auth(auth_key
->GetSecret(), auth_key
->GetLabel());
283 cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
287 base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete
,
294 void ExtendedAuthenticatorImpl::OnMountComplete(
295 const std::string
& time_marker
,
296 const UserContext
& user_context
,
297 const ResultCallback
& success_callback
,
299 cryptohome::MountError return_code
,
300 const std::string
& mount_hash
) {
301 RecordEndMarker(time_marker
);
302 UserContext copy
= user_context
;
303 copy
.SetUserIDHash(mount_hash
);
304 if (return_code
== cryptohome::MOUNT_ERROR_NONE
) {
305 if (!success_callback
.is_null())
306 success_callback
.Run(mount_hash
);
308 old_consumer_
->OnAuthSuccess(copy
);
311 AuthState state
= FAILED_MOUNT
;
312 if (return_code
== cryptohome::MOUNT_ERROR_TPM_COMM_ERROR
||
313 return_code
== cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK
||
314 return_code
== cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT
) {
317 if (return_code
== cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST
) {
321 consumer_
->OnAuthenticationFailure(state
);
323 AuthFailure
failure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME
);
324 old_consumer_
->OnAuthFailure(failure
);
328 void ExtendedAuthenticatorImpl::OnOperationComplete(
329 const std::string
& time_marker
,
330 const UserContext
& user_context
,
331 const base::Closure
& success_callback
,
333 cryptohome::MountError return_code
) {
334 RecordEndMarker(time_marker
);
335 if (return_code
== cryptohome::MOUNT_ERROR_NONE
) {
336 if (!success_callback
.is_null())
337 success_callback
.Run();
339 old_consumer_
->OnAuthSuccess(user_context
);
343 LOG(ERROR
) << "Supervised user cryptohome error, code: " << return_code
;
345 AuthState state
= FAILED_MOUNT
;
347 if (return_code
== cryptohome::MOUNT_ERROR_TPM_COMM_ERROR
||
348 return_code
== cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK
||
349 return_code
== cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT
) {
353 if (return_code
== cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST
)
357 consumer_
->OnAuthenticationFailure(state
);
360 AuthFailure
failure(AuthFailure::UNLOCK_FAILED
);
361 old_consumer_
->OnAuthFailure(failure
);
365 } // namespace chromeos