OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/cryptohome/cryptohome_library.h" | 5 #include "chromeos/cryptohome/cryptohome_library.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/memory/weak_ptr.h" | 10 #include "base/memory/weak_ptr.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
13 #include "base/sys_info.h" | 13 #include "base/sys_info.h" |
14 #include "chromeos/dbus/cryptohome_client.h" | 14 #include "chromeos/dbus/cryptohome_client.h" |
15 #include "chromeos/dbus/dbus_method_call_status.h" | 15 #include "chromeos/dbus/dbus_method_call_status.h" |
16 #include "chromeos/dbus/dbus_thread_manager.h" | 16 #include "chromeos/dbus/dbus_thread_manager.h" |
17 #include "crypto/encryptor.h" | |
18 #include "crypto/nss_util.h" | |
19 #include "crypto/sha2.h" | |
20 #include "crypto/symmetric_key.h" | |
21 | 17 |
22 namespace chromeos { | 18 namespace chromeos { |
23 | 19 |
24 namespace { | 20 namespace { |
25 | 21 |
26 const char kStubSystemSalt[] = "stub_system_salt"; | 22 const char kStubSystemSalt[] = "stub_system_salt"; |
27 const size_t kNonceSize = 16; | |
28 | 23 |
29 } // namespace | 24 } // namespace |
30 | 25 |
31 // This class handles the interaction with the ChromeOS cryptohome library APIs. | 26 // This class handles the interaction with the ChromeOS cryptohome library APIs. |
32 class CryptohomeLibraryImpl : public CryptohomeLibrary { | 27 class CryptohomeLibraryImpl : public CryptohomeLibrary { |
33 public: | 28 public: |
34 CryptohomeLibraryImpl() { | 29 CryptohomeLibraryImpl() { |
35 } | 30 } |
36 | 31 |
37 virtual ~CryptohomeLibraryImpl() { | 32 virtual ~CryptohomeLibraryImpl() { |
38 } | 33 } |
39 | 34 |
40 virtual std::string GetSystemSalt() OVERRIDE { | 35 virtual std::string GetSystemSalt() OVERRIDE { |
41 LoadSystemSalt(); // no-op if it's already loaded. | 36 LoadSystemSalt(); // no-op if it's already loaded. |
42 return system_salt_; | 37 return system_salt_; |
43 } | 38 } |
44 | 39 |
45 virtual std::string EncryptWithSystemSalt(const std::string& token) OVERRIDE { | 40 virtual std::string GetCachedSystemSalt() OVERRIDE { |
46 // Don't care about token encryption while debugging. | 41 return system_salt_; |
47 if (!base::SysInfo::IsRunningOnChromeOS()) | |
48 return token; | |
49 | |
50 if (!LoadSystemSaltKey()) { | |
51 LOG(WARNING) << "System salt key is not available for encrypt."; | |
52 return std::string(); | |
53 } | |
54 return EncryptTokenWithKey(system_salt_key_.get(), | |
55 system_salt_, | |
56 token); | |
57 } | |
58 | |
59 virtual std::string DecryptWithSystemSalt( | |
60 const std::string& encrypted_token_hex) OVERRIDE { | |
61 // Don't care about token encryption while debugging. | |
62 if (!base::SysInfo::IsRunningOnChromeOS()) | |
63 return encrypted_token_hex; | |
64 | |
65 if (!LoadSystemSaltKey()) { | |
66 LOG(WARNING) << "System salt key is not available for decrypt."; | |
67 return std::string(); | |
68 } | |
69 return DecryptTokenWithKey(system_salt_key_.get(), | |
70 system_salt_, | |
71 encrypted_token_hex); | |
72 } | 42 } |
73 | 43 |
74 private: | 44 private: |
75 void LoadSystemSalt() { | 45 void LoadSystemSalt() { |
76 if (!system_salt_.empty()) | 46 if (!system_salt_.empty()) |
77 return; | 47 return; |
78 std::vector<uint8> salt; | 48 std::vector<uint8> salt; |
79 DBusThreadManager::Get()->GetCryptohomeClient()->GetSystemSalt(&salt); | 49 DBusThreadManager::Get()->GetCryptohomeClient()->GetSystemSalt(&salt); |
80 if (salt.empty() || salt.size() % 2 != 0U) { | 50 if (salt.empty() || salt.size() % 2 != 0U) { |
81 LOG(WARNING) << "System salt not available"; | 51 LOG(WARNING) << "System salt not available"; |
82 return; | 52 return; |
83 } | 53 } |
84 system_salt_ = StringToLowerASCII(base::HexEncode( | 54 system_salt_ = StringToLowerASCII(base::HexEncode( |
85 reinterpret_cast<const void*>(salt.data()), salt.size())); | 55 reinterpret_cast<const void*>(salt.data()), salt.size())); |
86 } | 56 } |
87 | 57 |
88 // TODO: should this use the system salt for both the password and the salt | |
89 // value, or should this use a separate salt value? | |
90 bool LoadSystemSaltKey() { | |
91 if (system_salt_.empty()) | |
92 return false; | |
93 if (!system_salt_key_.get()) | |
94 system_salt_key_.reset(PassphraseToKey(system_salt_, system_salt_)); | |
95 return system_salt_key_.get(); | |
96 } | |
97 | |
98 crypto::SymmetricKey* PassphraseToKey(const std::string& passphrase, | |
99 const std::string& salt) { | |
100 return crypto::SymmetricKey::DeriveKeyFromPassword( | |
101 crypto::SymmetricKey::AES, passphrase, salt, 1000, 256); | |
102 } | |
103 | |
104 | |
105 // Encrypts (AES) the token given |key| and |salt|. | |
106 std::string EncryptTokenWithKey(crypto::SymmetricKey* key, | |
107 const std::string& salt, | |
108 const std::string& token) { | |
109 crypto::Encryptor encryptor; | |
110 if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) { | |
111 LOG(WARNING) << "Failed to initialize Encryptor."; | |
112 return std::string(); | |
113 } | |
114 std::string nonce = salt.substr(0, kNonceSize); | |
115 std::string encoded_token; | |
116 CHECK(encryptor.SetCounter(nonce)); | |
117 if (!encryptor.Encrypt(token, &encoded_token)) { | |
118 LOG(WARNING) << "Failed to encrypt token."; | |
119 return std::string(); | |
120 } | |
121 | |
122 return StringToLowerASCII(base::HexEncode( | |
123 reinterpret_cast<const void*>(encoded_token.data()), | |
124 encoded_token.size())); | |
125 } | |
126 | |
127 // Decrypts (AES) hex encoded encrypted token given |key| and |salt|. | |
128 std::string DecryptTokenWithKey(crypto::SymmetricKey* key, | |
129 const std::string& salt, | |
130 const std::string& encrypted_token_hex) { | |
131 std::vector<uint8> encrypted_token_bytes; | |
132 if (!base::HexStringToBytes(encrypted_token_hex, &encrypted_token_bytes)) { | |
133 LOG(WARNING) << "Corrupt encrypted token found."; | |
134 return std::string(); | |
135 } | |
136 | |
137 std::string encrypted_token( | |
138 reinterpret_cast<char*>(encrypted_token_bytes.data()), | |
139 encrypted_token_bytes.size()); | |
140 crypto::Encryptor encryptor; | |
141 if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) { | |
142 LOG(WARNING) << "Failed to initialize Encryptor."; | |
143 return std::string(); | |
144 } | |
145 | |
146 std::string nonce = salt.substr(0, kNonceSize); | |
147 std::string token; | |
148 CHECK(encryptor.SetCounter(nonce)); | |
149 if (!encryptor.Decrypt(encrypted_token, &token)) { | |
150 LOG(WARNING) << "Failed to decrypt token."; | |
151 return std::string(); | |
152 } | |
153 return token; | |
154 } | |
155 | |
156 std::string system_salt_; | 58 std::string system_salt_; |
157 // A key based on the system salt. Useful for encrypting device-level | |
158 // data for which we have no additional credentials. | |
159 scoped_ptr<crypto::SymmetricKey> system_salt_key_; | |
160 | 59 |
161 DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryImpl); | 60 DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryImpl); |
162 }; | 61 }; |
163 | 62 |
164 class CryptohomeLibraryStubImpl : public CryptohomeLibrary { | 63 class CryptohomeLibraryStubImpl : public CryptohomeLibrary { |
165 public: | 64 public: |
166 CryptohomeLibraryStubImpl() | 65 CryptohomeLibraryStubImpl() |
167 : locked_(false) {} | 66 : locked_(false) {} |
168 virtual ~CryptohomeLibraryStubImpl() {} | 67 virtual ~CryptohomeLibraryStubImpl() {} |
169 | 68 |
170 virtual std::string GetSystemSalt() OVERRIDE { | 69 virtual std::string GetSystemSalt() OVERRIDE { |
171 return kStubSystemSalt; | 70 return kStubSystemSalt; |
172 } | 71 } |
173 | 72 |
174 virtual std::string EncryptWithSystemSalt(const std::string& token) OVERRIDE { | 73 virtual std::string GetCachedSystemSalt() OVERRIDE { |
175 return token; | 74 return kStubSystemSalt; |
176 } | |
177 | |
178 virtual std::string DecryptWithSystemSalt( | |
179 const std::string& encrypted_token_hex) OVERRIDE { | |
180 return encrypted_token_hex; | |
181 } | 75 } |
182 | 76 |
183 private: | 77 private: |
184 std::map<std::string, std::string> install_attrs_; | 78 std::map<std::string, std::string> install_attrs_; |
185 bool locked_; | 79 bool locked_; |
hashimoto
2013/10/04 08:38:56
nit: Can we remove these two members? It seems the
satorux1
2013/10/07 02:19:14
Good catch. Forgot to remove them earlier. Done!
| |
186 DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryStubImpl); | 80 DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryStubImpl); |
187 }; | 81 }; |
188 | 82 |
189 CryptohomeLibrary::CryptohomeLibrary() {} | 83 CryptohomeLibrary::CryptohomeLibrary() {} |
190 CryptohomeLibrary::~CryptohomeLibrary() {} | 84 CryptohomeLibrary::~CryptohomeLibrary() {} |
191 | 85 |
192 static CryptohomeLibrary* g_cryptohome_library = NULL; | 86 static CryptohomeLibrary* g_cryptohome_library = NULL; |
193 static CryptohomeLibrary* g_test_cryptohome_library = NULL; | 87 static CryptohomeLibrary* g_test_cryptohome_library = NULL; |
194 | 88 |
195 // static | 89 // static |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 CHECK(!g_test_cryptohome_library || !impl); | 121 CHECK(!g_test_cryptohome_library || !impl); |
228 g_test_cryptohome_library = impl; | 122 g_test_cryptohome_library = impl; |
229 } | 123 } |
230 | 124 |
231 // static | 125 // static |
232 CryptohomeLibrary* CryptohomeLibrary::GetTestImpl() { | 126 CryptohomeLibrary* CryptohomeLibrary::GetTestImpl() { |
233 return new CryptohomeLibraryStubImpl(); | 127 return new CryptohomeLibraryStubImpl(); |
234 } | 128 } |
235 | 129 |
236 } // namespace chromeos | 130 } // namespace chromeos |
OLD | NEW |