1 // Copyright (c) 2012 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 "chromeos/cryptohome/system_salt_getter.h"
6
7 #include <stdint.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "base/threading/thread_task_runner_handle.h"
18 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
19
20 namespace chromeos {
21 namespace {
22
23 SystemSaltGetter* g_system_salt_getter = NULL;
24
25 } // namespace
26
SystemSaltGetter()27 SystemSaltGetter::SystemSaltGetter() {}
28
29 SystemSaltGetter::~SystemSaltGetter() = default;
30
GetSystemSalt(GetSystemSaltCallback callback)31 void SystemSaltGetter::GetSystemSalt(GetSystemSaltCallback callback) {
32 if (!system_salt_.empty()) {
33 base::ThreadTaskRunnerHandle::Get()->PostTask(
34 FROM_HERE, base::BindOnce(std::move(callback), system_salt_));
35 return;
36 }
37
38 CryptohomeClient::Get()->WaitForServiceToBeAvailable(
39 base::BindOnce(&SystemSaltGetter::DidWaitForServiceToBeAvailable,
40 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
41 }
42
AddOnSystemSaltReady(base::OnceClosure closure)43 void SystemSaltGetter::AddOnSystemSaltReady(base::OnceClosure closure) {
44 if (!raw_salt_.empty()) {
45 std::move(closure).Run();
46 return;
47 }
48
49 on_system_salt_ready_.push_back(std::move(closure));
50 }
51
GetRawSalt() const52 const SystemSaltGetter::RawSalt* SystemSaltGetter::GetRawSalt() const {
53 return raw_salt_.empty() ? nullptr : &raw_salt_;
54 }
55
SetRawSaltForTesting(const SystemSaltGetter::RawSalt & raw_salt)56 void SystemSaltGetter::SetRawSaltForTesting(
57 const SystemSaltGetter::RawSalt& raw_salt) {
58 raw_salt_ = raw_salt;
59 }
60
DidWaitForServiceToBeAvailable(GetSystemSaltCallback callback,bool service_is_available)61 void SystemSaltGetter::DidWaitForServiceToBeAvailable(
62 GetSystemSaltCallback callback,
63 bool service_is_available) {
64 if (!service_is_available) {
65 LOG(ERROR) << "WaitForServiceToBeAvailable failed.";
66 std::move(callback).Run(std::string());
67 return;
68 }
69 CryptohomeClient::Get()->GetSystemSalt(
70 base::BindOnce(&SystemSaltGetter::DidGetSystemSalt,
71 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
72 }
73
DidGetSystemSalt(GetSystemSaltCallback callback,base::Optional<std::vector<uint8_t>> system_salt)74 void SystemSaltGetter::DidGetSystemSalt(
75 GetSystemSaltCallback callback,
76 base::Optional<std::vector<uint8_t>> system_salt) {
77 if (system_salt.has_value() && !system_salt->empty() &&
78 system_salt->size() % 2 == 0U) {
79 raw_salt_ = std::move(system_salt).value();
80 system_salt_ = ConvertRawSaltToHexString(raw_salt_);
81
82 std::vector<base::OnceClosure> callbacks;
83 callbacks.swap(on_system_salt_ready_);
84 for (base::OnceClosure& callback : callbacks) {
85 std::move(callback).Run();
86 }
87 } else {
88 LOG(WARNING) << "System salt not available";
89 }
90
91 std::move(callback).Run(system_salt_);
92 }
93
94 // static
Initialize()95 void SystemSaltGetter::Initialize() {
96 CHECK(!g_system_salt_getter);
97 g_system_salt_getter = new SystemSaltGetter();
98 }
99
100 // static
IsInitialized()101 bool SystemSaltGetter::IsInitialized() {
102 return g_system_salt_getter;
103 }
104
105 // static
Shutdown()106 void SystemSaltGetter::Shutdown() {
107 CHECK(g_system_salt_getter);
108 delete g_system_salt_getter;
109 g_system_salt_getter = NULL;
110 }
111
112 // static
Get()113 SystemSaltGetter* SystemSaltGetter::Get() {
114 CHECK(g_system_salt_getter)
115 << "SystemSaltGetter::Get() called before Initialize()";
116 return g_system_salt_getter;
117 }
118
119 // static
ConvertRawSaltToHexString(const std::vector<uint8_t> & salt)120 std::string SystemSaltGetter::ConvertRawSaltToHexString(
121 const std::vector<uint8_t>& salt) {
122 return base::ToLowerASCII(
123 base::HexEncode(reinterpret_cast<const void*>(salt.data()), salt.size()));
124 }
125
126 } // namespace chromeos
127