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.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"
22 #include "third_party/cros_system_api/dbus/service_constants.h"
28 void RecordStartMarker(const std::string
& marker
) {
29 std::string full_marker
= "Cryptohome-";
30 full_marker
.append(marker
);
31 full_marker
.append("-Start");
32 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker
, false);
35 void RecordEndMarker(const std::string
& marker
) {
36 std::string full_marker
= "Cryptohome-";
37 full_marker
.append(marker
);
38 full_marker
.append("-End");
39 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker
, false);
44 ExtendedAuthenticator::ExtendedAuthenticator(NewAuthStatusConsumer
* consumer
)
45 : salt_obtained_(false), consumer_(consumer
), old_consumer_(NULL
) {
46 SystemSaltGetter::Get()->GetSystemSalt(
47 base::Bind(&ExtendedAuthenticator::OnSaltObtained
, this));
50 ExtendedAuthenticator::ExtendedAuthenticator(AuthStatusConsumer
* consumer
)
51 : salt_obtained_(false), consumer_(NULL
), old_consumer_(consumer
) {
52 SystemSaltGetter::Get()->GetSystemSalt(
53 base::Bind(&ExtendedAuthenticator::OnSaltObtained
, this));
56 void ExtendedAuthenticator::SetConsumer(AuthStatusConsumer
* consumer
) {
57 old_consumer_
= consumer
;
60 void ExtendedAuthenticator::AuthenticateToMount(
61 const UserContext
& context
,
62 const ResultCallback
& success_callback
) {
63 TransformKeyIfNeeded(context
,
64 base::Bind(&ExtendedAuthenticator::DoAuthenticateToMount
,
69 void ExtendedAuthenticator::AuthenticateToCheck(
70 const UserContext
& context
,
71 const base::Closure
& success_callback
) {
72 TransformKeyIfNeeded(context
,
73 base::Bind(&ExtendedAuthenticator::DoAuthenticateToCheck
,
78 void ExtendedAuthenticator::CreateMount(
79 const std::string
& user_id
,
80 const std::vector
<cryptohome::KeyDefinition
>& keys
,
81 const ResultCallback
& success_callback
) {
82 RecordStartMarker("MountEx");
84 std::string canonicalized
= gaia::CanonicalizeEmail(user_id
);
85 cryptohome::Identification
id(canonicalized
);
86 cryptohome::Authorization
auth(keys
.front());
87 cryptohome::MountParameters
mount(false);
88 for (size_t i
= 0; i
< keys
.size(); i
++) {
89 mount
.create_keys
.push_back(keys
[i
]);
91 UserContext
context(user_id
);
92 Key
key(keys
.front().secret
);
93 key
.SetLabel(keys
.front().label
);
96 cryptohome::HomedirMethods::GetInstance()->MountEx(
100 base::Bind(&ExtendedAuthenticator::OnMountComplete
,
107 void ExtendedAuthenticator::AddKey(const UserContext
& context
,
108 const cryptohome::KeyDefinition
& key
,
109 bool replace_existing
,
110 const base::Closure
& success_callback
) {
111 TransformKeyIfNeeded(context
,
112 base::Bind(&ExtendedAuthenticator::DoAddKey
,
119 void ExtendedAuthenticator::UpdateKeyAuthorized(
120 const UserContext
& context
,
121 const cryptohome::KeyDefinition
& key
,
122 const std::string
& signature
,
123 const base::Closure
& success_callback
) {
124 TransformKeyIfNeeded(context
,
125 base::Bind(&ExtendedAuthenticator::DoUpdateKeyAuthorized
,
132 void ExtendedAuthenticator::RemoveKey(const UserContext
& context
,
133 const std::string
& key_to_remove
,
134 const base::Closure
& success_callback
) {
135 TransformKeyIfNeeded(context
,
136 base::Bind(&ExtendedAuthenticator::DoRemoveKey
,
142 void ExtendedAuthenticator::TransformKeyIfNeeded(
143 const UserContext
& user_context
,
144 const ContextCallback
& callback
) {
145 if (user_context
.GetKey()->GetKeyType() != Key::KEY_TYPE_PASSWORD_PLAIN
) {
146 callback
.Run(user_context
);
150 if (!salt_obtained_
) {
151 system_salt_callbacks_
.push_back(
152 base::Bind(&ExtendedAuthenticator::TransformKeyIfNeeded
,
159 UserContext transformed_context
= user_context
;
160 transformed_context
.GetKey()->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF
,
162 callback
.Run(transformed_context
);
165 ExtendedAuthenticator::~ExtendedAuthenticator() {
168 void ExtendedAuthenticator::OnSaltObtained(const std::string
& system_salt
) {
169 salt_obtained_
= true;
170 system_salt_
= system_salt
;
171 for (std::vector
<base::Closure
>::const_iterator it
=
172 system_salt_callbacks_
.begin();
173 it
!= system_salt_callbacks_
.end();
177 system_salt_callbacks_
.clear();
180 void ExtendedAuthenticator::DoAuthenticateToMount(
181 const ResultCallback
& success_callback
,
182 const UserContext
& user_context
) {
183 RecordStartMarker("MountEx");
185 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
186 cryptohome::Identification
id(canonicalized
);
187 const Key
* const key
= user_context
.GetKey();
188 cryptohome::Authorization
auth(key
->GetSecret(), key
->GetLabel());
189 cryptohome::MountParameters
mount(false);
191 cryptohome::HomedirMethods::GetInstance()->MountEx(
195 base::Bind(&ExtendedAuthenticator::OnMountComplete
,
202 void ExtendedAuthenticator::DoAuthenticateToCheck(
203 const base::Closure
& success_callback
,
204 const UserContext
& user_context
) {
205 RecordStartMarker("CheckKeyEx");
207 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
208 cryptohome::Identification
id(canonicalized
);
209 const Key
* const key
= user_context
.GetKey();
210 cryptohome::Authorization
auth(key
->GetSecret(), key
->GetLabel());
212 cryptohome::HomedirMethods::GetInstance()->CheckKeyEx(
215 base::Bind(&ExtendedAuthenticator::OnOperationComplete
,
222 void ExtendedAuthenticator::DoAddKey(const cryptohome::KeyDefinition
& key
,
223 bool replace_existing
,
224 const base::Closure
& success_callback
,
225 const UserContext
& user_context
) {
226 RecordStartMarker("AddKeyEx");
228 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
229 cryptohome::Identification
id(canonicalized
);
230 const Key
* const auth_key
= user_context
.GetKey();
231 cryptohome::Authorization
auth(auth_key
->GetSecret(), auth_key
->GetLabel());
233 cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
238 base::Bind(&ExtendedAuthenticator::OnOperationComplete
,
245 void ExtendedAuthenticator::DoUpdateKeyAuthorized(
246 const cryptohome::KeyDefinition
& key
,
247 const std::string
& signature
,
248 const base::Closure
& success_callback
,
249 const UserContext
& user_context
) {
250 RecordStartMarker("UpdateKeyAuthorized");
252 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
253 cryptohome::Identification
id(canonicalized
);
254 const Key
* const auth_key
= user_context
.GetKey();
255 cryptohome::Authorization
auth(auth_key
->GetSecret(), auth_key
->GetLabel());
257 cryptohome::HomedirMethods::GetInstance()->UpdateKeyEx(
262 base::Bind(&ExtendedAuthenticator::OnOperationComplete
,
264 "UpdateKeyAuthorized",
269 void ExtendedAuthenticator::DoRemoveKey(const std::string
& key_to_remove
,
270 const base::Closure
& success_callback
,
271 const UserContext
& user_context
) {
272 RecordStartMarker("RemoveKeyEx");
274 std::string canonicalized
= gaia::CanonicalizeEmail(user_context
.GetUserID());
275 cryptohome::Identification
id(canonicalized
);
276 const Key
* const auth_key
= user_context
.GetKey();
277 cryptohome::Authorization
auth(auth_key
->GetSecret(), auth_key
->GetLabel());
279 cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
283 base::Bind(&ExtendedAuthenticator::OnOperationComplete
,
290 void ExtendedAuthenticator::OnMountComplete(
291 const std::string
& time_marker
,
292 const UserContext
& user_context
,
293 const ResultCallback
& success_callback
,
295 cryptohome::MountError return_code
,
296 const std::string
& mount_hash
) {
297 RecordEndMarker(time_marker
);
298 UserContext copy
= user_context
;
299 copy
.SetUserIDHash(mount_hash
);
300 if (return_code
== cryptohome::MOUNT_ERROR_NONE
) {
301 if (!success_callback
.is_null())
302 success_callback
.Run(mount_hash
);
304 old_consumer_
->OnAuthSuccess(copy
);
307 AuthState state
= FAILED_MOUNT
;
308 if (return_code
== cryptohome::MOUNT_ERROR_TPM_COMM_ERROR
||
309 return_code
== cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK
||
310 return_code
== cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT
) {
313 if (return_code
== cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST
) {
317 consumer_
->OnAuthenticationFailure(state
);
319 AuthFailure
failure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME
);
320 old_consumer_
->OnAuthFailure(failure
);
324 void ExtendedAuthenticator::OnOperationComplete(
325 const std::string
& time_marker
,
326 const UserContext
& user_context
,
327 const base::Closure
& success_callback
,
329 cryptohome::MountError return_code
) {
330 RecordEndMarker(time_marker
);
331 if (return_code
== cryptohome::MOUNT_ERROR_NONE
) {
332 if (!success_callback
.is_null())
333 success_callback
.Run();
335 old_consumer_
->OnAuthSuccess(user_context
);
339 LOG(ERROR
) << "Supervised user cryptohome error, code: " << return_code
;
341 AuthState state
= FAILED_MOUNT
;
343 if (return_code
== cryptohome::MOUNT_ERROR_TPM_COMM_ERROR
||
344 return_code
== cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK
||
345 return_code
== cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT
) {
349 if (return_code
== cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST
)
353 consumer_
->OnAuthenticationFailure(state
);
356 AuthFailure
failure(AuthFailure::UNLOCK_FAILED
);
357 old_consumer_
->OnAuthFailure(failure
);
361 } // namespace chromeos