blob: dcdcd62f105fc5ed3ee122d109e53aff3fb5c25a [file] [log] [blame]
Paul Lawrence707fd6c2015-04-28 22:14:15 +00001#include "Ext4Crypt.h"
2
Paul Lawrence5e7f0042015-04-10 07:48:51 -07003#include <iomanip>
Paul Lawrence707fd6c2015-04-28 22:14:15 +00004#include <map>
Paul Lawrence5e7f0042015-04-10 07:48:51 -07005#include <fstream>
6#include <string>
7#include <sstream>
Paul Lawrence707fd6c2015-04-28 22:14:15 +00008
9#include <errno.h>
10#include <sys/mount.h>
11#include <cutils/properties.h>
Paul Lawrence5e7f0042015-04-10 07:48:51 -070012#include <openssl/sha.h>
Paul Lawrence707fd6c2015-04-28 22:14:15 +000013
14#include "unencrypted_properties.h"
15#include "key_control.h"
16#include "cryptfs.h"
17
18#define LOG_TAG "Ext4Crypt"
19#include "cutils/log.h"
20#include <cutils/klog.h>
21
22namespace {
23 // Key length in bits
24 const int key_length = 128;
Paul Lawrence5e7f0042015-04-10 07:48:51 -070025 static_assert(key_length % 8 == 0,
26 "Key length must be multiple of 8 bits");
Paul Lawrence707fd6c2015-04-28 22:14:15 +000027
28 // How is device encrypted
29 struct keys {
30 std::string master_key;
31 std::string password;
32 };
33 std::map<std::string, keys> s_key_store;
34
Paul Lawrence5e7f0042015-04-10 07:48:51 -070035 // ext4enc:TODO get these consts from somewhere good
36 const int SHA512_LENGTH = 64;
37 const int EXT4_KEY_DESCRIPTOR_SIZE = 8;
38
Paul Lawrence707fd6c2015-04-28 22:14:15 +000039 // ext4enc:TODO Include structure from somewhere sensible
40 // MUST be in sync with ext4_crypto.c in kernel
Paul Lawrence5e7f0042015-04-10 07:48:51 -070041 const int EXT4_MAX_KEY_SIZE = 64;
42 const int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1;
Paul Lawrence707fd6c2015-04-28 22:14:15 +000043 struct ext4_encryption_key {
Paul Lawrence5e7f0042015-04-10 07:48:51 -070044 uint32_t mode;
45 char raw[EXT4_MAX_KEY_SIZE];
46 uint32_t size;
Paul Lawrence707fd6c2015-04-28 22:14:15 +000047 };
48
49 namespace tag {
50 const char* magic = "magic";
51 const char* major_version = "major_version";
52 const char* minor_version = "minor_version";
53 const char* flags = "flags";
54 const char* crypt_type = "crypt_type";
55 const char* failed_decrypt_count = "failed_decrypt_count";
56 const char* crypto_type_name = "crypto_type_name";
57 const char* master_key = "master_key";
58 const char* salt = "salt";
59 const char* kdf_type = "kdf_type";
60 const char* N_factor = "N_factor";
61 const char* r_factor = "r_factor";
62 const char* p_factor = "p_factor";
63 const char* keymaster_blob = "keymaster_blob";
64 const char* scrypted_intermediate_key = "scrypted_intermediate_key";
65 }
66}
67
68static int put_crypt_ftr_and_key(const crypt_mnt_ftr& crypt_ftr,
69 UnencryptedProperties& props)
70{
71 SLOGI("Putting crypt footer");
72
73 bool success = props.Set<int>(tag::magic, crypt_ftr.magic)
74 && props.Set<int>(tag::major_version, crypt_ftr.major_version)
75 && props.Set<int>(tag::minor_version, crypt_ftr.minor_version)
76 && props.Set<int>(tag::flags, crypt_ftr.flags)
77 && props.Set<int>(tag::crypt_type, crypt_ftr.crypt_type)
78 && props.Set<int>(tag::failed_decrypt_count,
79 crypt_ftr.failed_decrypt_count)
80 && props.Set<std::string>(tag::crypto_type_name,
81 std::string(reinterpret_cast<const char*>(crypt_ftr.crypto_type_name)))
82 && props.Set<std::string>(tag::master_key,
83 std::string((const char*) crypt_ftr.master_key,
84 crypt_ftr.keysize))
85 && props.Set<std::string>(tag::salt,
86 std::string((const char*) crypt_ftr.salt,
87 SALT_LEN))
88 && props.Set<int>(tag::kdf_type, crypt_ftr.kdf_type)
89 && props.Set<int>(tag::N_factor, crypt_ftr.N_factor)
90 && props.Set<int>(tag::r_factor, crypt_ftr.r_factor)
91 && props.Set<int>(tag::p_factor, crypt_ftr.p_factor)
92 && props.Set<std::string>(tag::keymaster_blob,
93 std::string((const char*) crypt_ftr.keymaster_blob,
94 crypt_ftr.keymaster_blob_size))
95 && props.Set<std::string>(tag::scrypted_intermediate_key,
96 std::string((const char*) crypt_ftr.scrypted_intermediate_key,
97 SCRYPT_LEN));
98 return success ? 0 : -1;
99}
100
101static int get_crypt_ftr_and_key(crypt_mnt_ftr& crypt_ftr,
102 const UnencryptedProperties& props)
103{
104 memset(&crypt_ftr, 0, sizeof(crypt_ftr));
105 crypt_ftr.magic = props.Get<int>(tag::magic);
106 crypt_ftr.major_version = props.Get<int>(tag::major_version);
107 crypt_ftr.minor_version = props.Get<int>(tag::minor_version);
Paul Lawrence75c922f2015-05-05 15:58:27 -0700108 crypt_ftr.ftr_size = sizeof(crypt_ftr);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000109 crypt_ftr.flags = props.Get<int>(tag::flags);
110 crypt_ftr.crypt_type = props.Get<int>(tag::crypt_type);
111 crypt_ftr.failed_decrypt_count = props.Get<int>(tag::failed_decrypt_count);
112 std::string crypto_type_name = props.Get<std::string>(tag::crypto_type_name);
113 strlcpy(reinterpret_cast<char*>(crypt_ftr.crypto_type_name),
114 crypto_type_name.c_str(),
115 sizeof(crypt_ftr.crypto_type_name));
116 std::string master_key = props.Get<std::string>(tag::master_key);
117 crypt_ftr.keysize = master_key.size();
118 if (crypt_ftr.keysize > sizeof(crypt_ftr.master_key)) {
119 SLOGE("Master key size too long");
120 return -1;
121 }
122 memcpy(crypt_ftr.master_key, &master_key[0], crypt_ftr.keysize);
123 std::string salt = props.Get<std::string>(tag::salt);
124 if (salt.size() != SALT_LEN) {
125 SLOGE("Salt wrong length");
126 return -1;
127 }
128 memcpy(crypt_ftr.salt, &salt[0], SALT_LEN);
129 crypt_ftr.kdf_type = props.Get<int>(tag::kdf_type);
130 crypt_ftr.N_factor = props.Get<int>(tag::N_factor);
131 crypt_ftr.r_factor = props.Get<int>(tag::r_factor);
132 crypt_ftr.p_factor = props.Get<int>(tag::p_factor);
133 std::string keymaster_blob = props.Get<std::string>(tag::keymaster_blob);
134 crypt_ftr.keymaster_blob_size = keymaster_blob.size();
135 if (crypt_ftr.keymaster_blob_size > sizeof(crypt_ftr.keymaster_blob)) {
136 SLOGE("Keymaster blob too long");
137 return -1;
138 }
139 memcpy(crypt_ftr.keymaster_blob, &keymaster_blob[0],
140 crypt_ftr.keymaster_blob_size);
141 std::string scrypted_intermediate_key = props.Get<std::string>(tag::scrypted_intermediate_key);
142 if (scrypted_intermediate_key.size() != SCRYPT_LEN) {
143 SLOGE("scrypted intermediate key wrong length");
144 return -1;
145 }
146 memcpy(crypt_ftr.scrypted_intermediate_key, &scrypted_intermediate_key[0],
147 SCRYPT_LEN);
148
149 return 0;
150}
151
152static UnencryptedProperties GetProps(const char* path)
153{
154 return UnencryptedProperties(path);
155}
156
157static UnencryptedProperties GetAltProps(const char* path)
158{
159 return UnencryptedProperties((std::string() + path + "/tmp_mnt").c_str());
160}
161
162static UnencryptedProperties GetPropsOrAltProps(const char* path)
163{
164 UnencryptedProperties props = GetProps(path);
165 if (props.OK()) {
166 return props;
167 }
168 return GetAltProps(path);
169}
170
171int e4crypt_enable(const char* path)
172{
173 // Already enabled?
174 if (s_key_store.find(path) != s_key_store.end()) {
175 return 0;
176 }
177
178 // Not an encryptable device?
179 UnencryptedProperties key_props = GetProps(path).GetChild(properties::key);
180 if (!key_props.OK()) {
181 return 0;
182 }
183
184 if (key_props.Get<std::string>(tag::master_key).empty()) {
185 crypt_mnt_ftr ftr;
186 if (cryptfs_create_default_ftr(&ftr, key_length)) {
187 SLOGE("Failed to create crypto footer");
188 return -1;
189 }
190
Paul Lawrence75c922f2015-05-05 15:58:27 -0700191 // Scrub fields not used by ext4enc
192 ftr.persist_data_offset[0] = 0;
193 ftr.persist_data_offset[1] = 0;
194 ftr.persist_data_size = 0;
195
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000196 if (put_crypt_ftr_and_key(ftr, key_props)) {
197 SLOGE("Failed to write crypto footer");
198 return -1;
199 }
200
201 crypt_mnt_ftr ftr2;
202 if (get_crypt_ftr_and_key(ftr2, key_props)) {
203 SLOGE("Failed to read crypto footer back");
204 return -1;
205 }
206
207 if (memcmp(&ftr, &ftr2, sizeof(ftr)) != 0) {
208 SLOGE("Crypto footer not correctly written");
Paul Lawrence75c922f2015-05-05 15:58:27 -0700209 return -1;
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000210 }
211 }
212
213 if (!UnencryptedProperties(path).Remove(properties::ref)) {
214 SLOGE("Failed to remove key ref");
215 return -1;
216 }
217
218 return e4crypt_check_passwd(path, "");
219}
220
221int e4crypt_change_password(const char* path, int crypt_type,
222 const char* password)
223{
224 SLOGI("e4crypt_change_password");
Paul Lawrenceaaccfac2015-05-04 15:48:24 -0700225 auto key_props = GetProps(path).GetChild(properties::key);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000226
227 crypt_mnt_ftr ftr;
228 if (get_crypt_ftr_and_key(ftr, key_props)) {
229 SLOGE("Failed to read crypto footer back");
230 return -1;
231 }
232
233 auto mki = s_key_store.find(path);
234 if (mki == s_key_store.end()) {
235 SLOGE("No stored master key - can't change password");
236 return -1;
237 }
238
239 const unsigned char* master_key
240 = reinterpret_cast<const unsigned char*>(&mki->second.master_key[0]);
241
242 if (cryptfs_set_password(&ftr, password, master_key)) {
243 SLOGE("Failed to set password");
244 return -1;
245 }
246
247 ftr.crypt_type = crypt_type;
248
249 if (put_crypt_ftr_and_key(ftr, key_props)) {
250 SLOGE("Failed to write crypto footer");
251 return -1;
252 }
253
254 if (!UnencryptedProperties(path).Set(properties::is_default,
255 crypt_type == CRYPT_TYPE_DEFAULT)) {
256 SLOGE("Failed to update default flag");
257 return -1;
258 }
259
260 return 0;
261}
262
263int e4crypt_crypto_complete(const char* path)
264{
265 SLOGI("ext4 crypto complete called on %s", path);
Paul Lawrenceaaccfac2015-05-04 15:48:24 -0700266 auto key_props = GetPropsOrAltProps(path).GetChild(properties::key);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000267 if (key_props.Get<std::string>(tag::master_key).empty()) {
268 SLOGI("No master key, so not ext4enc");
269 return -1;
270 }
271
272 return 0;
273}
274
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700275static std::string generate_key_ref(const char* key, int length)
276{
277 SHA512_CTX c;
278
279 SHA512_Init(&c);
280 SHA512_Update(&c, key, length);
281 unsigned char key_ref1[SHA512_LENGTH];
282 SHA512_Final(key_ref1, &c);
283
284 SHA512_Init(&c);
285 SHA512_Update(&c, key_ref1, SHA512_LENGTH);
286 unsigned char key_ref2[SHA512_LENGTH];
287 SHA512_Final(key_ref2, &c);
288
289 return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE);
290}
291
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000292int e4crypt_check_passwd(const char* path, const char* password)
293{
294 SLOGI("e4crypt_check_password");
Paul Lawrenceaaccfac2015-05-04 15:48:24 -0700295 auto props = GetPropsOrAltProps(path);
296 auto key_props = props.GetChild(properties::key);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000297
298 crypt_mnt_ftr ftr;
299 if (get_crypt_ftr_and_key(ftr, key_props)) {
300 SLOGE("Failed to read crypto footer back");
301 return -1;
302 }
303
304 unsigned char master_key[key_length / 8];
305 if (cryptfs_get_master_key (&ftr, password, master_key)){
306 SLOGI("Incorrect password");
Paul Lawrence3ca21e22015-04-14 15:26:29 -0700307 ftr.failed_decrypt_count++;
308 if (put_crypt_ftr_and_key(ftr, key_props)) {
309 SLOGW("Failed to update failed_decrypt_count");
310 }
311 return ftr.failed_decrypt_count;
312 }
313
314 if (ftr.failed_decrypt_count) {
315 ftr.failed_decrypt_count = 0;
316 if (put_crypt_ftr_and_key(ftr, key_props)) {
317 SLOGW("Failed to reset failed_decrypt_count");
318 }
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000319 }
320
321 s_key_store[path] = keys{std::string(reinterpret_cast<char*>(master_key),
322 sizeof(master_key)),
323 password};
324
325 // Install password into global keyring
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700326 // ext4enc:TODO Currently raw key is required to be of length
327 // sizeof(ext4_key.raw) == EXT4_MAX_KEY_SIZE, so zero pad to
328 // this length. Change when kernel bug is fixed.
329 ext4_encryption_key ext4_key = {EXT4_ENCRYPTION_MODE_AES_256_XTS,
330 {0},
331 sizeof(ext4_key.raw)};
332 memset(ext4_key.raw, 0, sizeof(ext4_key.raw));
333 static_assert(key_length / 8 <= sizeof(ext4_key.raw),
334 "Key too long!");
335 memcpy(ext4_key.raw, master_key, key_length / 8);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000336
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700337 // Get raw keyref - used to make keyname and to pass to ioctl
338 auto raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size);
339
340 // Generate keyname
341 std::ostringstream o;
342 for (auto i = raw_ref.begin(); i != raw_ref.end(); ++i) {
343 o << std::hex << std::setw(2) << std::setfill('0') << (int)*i;
344 }
345 auto ref = std::string("ext4:") + o.str();
346
347 // Find existing keyring
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000348 key_serial_t device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING,
349 "keyring", "e4crypt", 0);
350
351 SLOGI("Found device_keyring - id is %d", device_keyring);
352
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700353 // Add key ...
354 key_serial_t key_id = add_key("logon", ref.c_str(),
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000355 (void*)&ext4_key, sizeof(ext4_key),
356 device_keyring);
357
358 if (key_id == -1) {
359 SLOGE("Failed to insert key into keyring with error %s",
360 strerror(errno));
361 return -1;
362 }
363
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700364 SLOGI("Added key %d (%s) to keyring %d in process %d",
365 key_id, ref.c_str(), device_keyring, getpid());
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000366
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000367 // Save reference to key so we can set policy later
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700368 if (!props.Set(properties::ref, raw_ref)) {
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000369 SLOGE("Cannot save key reference");
370 return -1;
371 }
372
373 return 0;
374}
375
376int e4crypt_restart(const char* path)
377{
378 SLOGI("e4crypt_restart");
379
380 int rc = 0;
381
382 SLOGI("ext4 restart called on %s", path);
383 property_set("vold.decrypt", "trigger_reset_main");
384 SLOGI("Just asked init to shut down class main");
385 sleep(2);
386
387 std::string tmp_path = std::string() + path + "/tmp_mnt";
388
Paul Lawrence29b54aa2015-05-05 14:28:25 -0700389 rc = wait_and_unmount(tmp_path.c_str(), true);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000390 if (rc) {
391 SLOGE("umount %s failed with rc %d, msg %s",
392 tmp_path.c_str(), rc, strerror(errno));
393 return rc;
394 }
395
Paul Lawrence29b54aa2015-05-05 14:28:25 -0700396 rc = wait_and_unmount(path, true);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000397 if (rc) {
398 SLOGE("umount %s failed with rc %d, msg %s",
399 path, rc, strerror(errno));
400 return rc;
401 }
402
403 return 0;
404}
405
406const char* e4crypt_get_password(const char* path)
407{
408 SLOGI("e4crypt_get_password");
409
410 // ext4enc:TODO scrub password after timeout
411 auto i = s_key_store.find(path);
412 if (i == s_key_store.end()) {
413 return 0;
414 } else {
415 return i->second.password.c_str();
416 }
417}
418
419int e4crypt_get_password_type(const char* path)
420{
421 SLOGI("e4crypt_get_password_type");
422 return GetPropsOrAltProps(path).GetChild(properties::key)
423 .Get<int>(tag::crypt_type, CRYPT_TYPE_DEFAULT);
424}
Paul Lawrence4e727452015-04-15 14:12:00 -0700425
426int e4crypt_get_field(const char* path, const char* fieldname,
427 char* value, size_t len)
428{
429 auto v = GetPropsOrAltProps(path).GetChild(properties::props)
430 .Get<std::string>(fieldname);
431
432 if (v == "") {
433 return CRYPTO_GETFIELD_ERROR_NO_FIELD;
434 }
435
436 if (v.length() >= len) {
437 return CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
438 }
439
440 strlcpy(value, v.c_str(), len);
441 return 0;
442}
443
444int e4crypt_set_field(const char* path, const char* fieldname,
445 const char* value)
446{
447 return GetPropsOrAltProps(path).GetChild(properties::props)
448 .Set(fieldname, std::string(value)) ? 0 : -1;
449}