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