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/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.h"
6
7#include "base/bind.h"
8#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
9#include "chromeos/cryptohome/homedir_methods.h"
10#include "chromeos/cryptohome/system_salt_getter.h"
11#include "google_apis/gaia/gaia_auth_util.h"
12
13namespace chromeos {
14
15EasyUnlockRemoveKeysOperation::EasyUnlockRemoveKeysOperation(
16    const UserContext& user_context,
17    size_t start_index,
18    const RemoveKeysCallback& callback)
19    : user_context_(user_context),
20      callback_(callback),
21      key_index_(start_index),
22      weak_ptr_factory_(this) {
23  // Must have the secret and callback.
24  DCHECK(!user_context_.GetKey()->GetSecret().empty());
25  DCHECK(!callback_.is_null());
26}
27
28EasyUnlockRemoveKeysOperation::~EasyUnlockRemoveKeysOperation() {
29}
30
31void EasyUnlockRemoveKeysOperation::Start() {
32  if (user_context_.GetKey()->GetKeyType() == Key::KEY_TYPE_PASSWORD_PLAIN) {
33    SystemSaltGetter::Get()->GetSystemSalt(
34        base::Bind(&EasyUnlockRemoveKeysOperation::OnGetSystemSalt,
35                   weak_ptr_factory_.GetWeakPtr()));
36    return;
37  }
38
39  RemoveKey();
40}
41
42void EasyUnlockRemoveKeysOperation::OnGetSystemSalt(
43    const std::string& system_salt) {
44  user_context_.GetKey()->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF,
45                                    system_salt);
46  RemoveKey();
47}
48
49void EasyUnlockRemoveKeysOperation::RemoveKey() {
50  std::string canonicalized =
51      gaia::CanonicalizeEmail(user_context_.GetUserID());
52  cryptohome::Identification id(canonicalized);
53  const Key* const auth_key = user_context_.GetKey();
54  cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
55
56  // TODO(xiyuan): Use ListKeyEx and delete by label instead of by index.
57  cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
58      id,
59      auth,
60      EasyUnlockKeyManager::GetKeyLabel(key_index_),
61      base::Bind(&EasyUnlockRemoveKeysOperation::OnKeyRemoved,
62                 weak_ptr_factory_.GetWeakPtr()));
63}
64
65void EasyUnlockRemoveKeysOperation::OnKeyRemoved(
66    bool success,
67    cryptohome::MountError return_code) {
68  if (success) {
69    ++key_index_;
70    RemoveKey();
71    return;
72  }
73
74  // MOUNT_ERROR_KEY_FAILURE is considered as success. Other error codes are
75  // treated as failures.
76  if (return_code == cryptohome::MOUNT_ERROR_KEY_FAILURE) {
77    callback_.Run(true);
78  } else {
79    LOG(ERROR) << "Easy unlock remove keys operation failed, code="
80               << return_code;
81    callback_.Run(false);
82  }
83}
84
85}  // namespace chromeos
86