blob: d1e22ec0729a82d2e432b8ef8e1ff811425ac95d [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
Paul Lawrence00f4aad2015-05-06 13:53:43 -070028 // How long do we store passwords for?
29 const int password_max_age_seconds = 60;
30
Paul Lawrence707fd6c2015-04-28 22:14:15 +000031 // How is device encrypted
32 struct keys {
33 std::string master_key;
34 std::string password;
Paul Lawrence00f4aad2015-05-06 13:53:43 -070035 time_t expiry_time;
Paul Lawrence707fd6c2015-04-28 22:14:15 +000036 };
37 std::map<std::string, keys> s_key_store;
38
Paul Lawrence5e7f0042015-04-10 07:48:51 -070039 // ext4enc:TODO get these consts from somewhere good
40 const int SHA512_LENGTH = 64;
41 const int EXT4_KEY_DESCRIPTOR_SIZE = 8;
42
Paul Lawrence707fd6c2015-04-28 22:14:15 +000043 // ext4enc:TODO Include structure from somewhere sensible
44 // MUST be in sync with ext4_crypto.c in kernel
Paul Lawrence5e7f0042015-04-10 07:48:51 -070045 const int EXT4_MAX_KEY_SIZE = 64;
46 const int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1;
Paul Lawrence707fd6c2015-04-28 22:14:15 +000047 struct ext4_encryption_key {
Paul Lawrence5e7f0042015-04-10 07:48:51 -070048 uint32_t mode;
49 char raw[EXT4_MAX_KEY_SIZE];
50 uint32_t size;
Paul Lawrence707fd6c2015-04-28 22:14:15 +000051 };
52
53 namespace tag {
54 const char* magic = "magic";
55 const char* major_version = "major_version";
56 const char* minor_version = "minor_version";
57 const char* flags = "flags";
58 const char* crypt_type = "crypt_type";
59 const char* failed_decrypt_count = "failed_decrypt_count";
60 const char* crypto_type_name = "crypto_type_name";
61 const char* master_key = "master_key";
62 const char* salt = "salt";
63 const char* kdf_type = "kdf_type";
64 const char* N_factor = "N_factor";
65 const char* r_factor = "r_factor";
66 const char* p_factor = "p_factor";
67 const char* keymaster_blob = "keymaster_blob";
68 const char* scrypted_intermediate_key = "scrypted_intermediate_key";
69 }
70}
71
Paul Crowley1da96dc2015-05-06 13:38:53 +010072static std::string e4crypt_install_key(const unsigned char *key_bytes);
73
Paul Lawrence707fd6c2015-04-28 22:14:15 +000074static int put_crypt_ftr_and_key(const crypt_mnt_ftr& crypt_ftr,
75 UnencryptedProperties& props)
76{
77 SLOGI("Putting crypt footer");
78
79 bool success = props.Set<int>(tag::magic, crypt_ftr.magic)
80 && props.Set<int>(tag::major_version, crypt_ftr.major_version)
81 && props.Set<int>(tag::minor_version, crypt_ftr.minor_version)
82 && props.Set<int>(tag::flags, crypt_ftr.flags)
83 && props.Set<int>(tag::crypt_type, crypt_ftr.crypt_type)
84 && props.Set<int>(tag::failed_decrypt_count,
85 crypt_ftr.failed_decrypt_count)
86 && props.Set<std::string>(tag::crypto_type_name,
87 std::string(reinterpret_cast<const char*>(crypt_ftr.crypto_type_name)))
88 && props.Set<std::string>(tag::master_key,
89 std::string((const char*) crypt_ftr.master_key,
90 crypt_ftr.keysize))
91 && props.Set<std::string>(tag::salt,
92 std::string((const char*) crypt_ftr.salt,
93 SALT_LEN))
94 && props.Set<int>(tag::kdf_type, crypt_ftr.kdf_type)
95 && props.Set<int>(tag::N_factor, crypt_ftr.N_factor)
96 && props.Set<int>(tag::r_factor, crypt_ftr.r_factor)
97 && props.Set<int>(tag::p_factor, crypt_ftr.p_factor)
98 && props.Set<std::string>(tag::keymaster_blob,
99 std::string((const char*) crypt_ftr.keymaster_blob,
100 crypt_ftr.keymaster_blob_size))
101 && props.Set<std::string>(tag::scrypted_intermediate_key,
102 std::string((const char*) crypt_ftr.scrypted_intermediate_key,
103 SCRYPT_LEN));
104 return success ? 0 : -1;
105}
106
107static int get_crypt_ftr_and_key(crypt_mnt_ftr& crypt_ftr,
108 const UnencryptedProperties& props)
109{
110 memset(&crypt_ftr, 0, sizeof(crypt_ftr));
111 crypt_ftr.magic = props.Get<int>(tag::magic);
112 crypt_ftr.major_version = props.Get<int>(tag::major_version);
113 crypt_ftr.minor_version = props.Get<int>(tag::minor_version);
Paul Lawrence75c922f2015-05-05 15:58:27 -0700114 crypt_ftr.ftr_size = sizeof(crypt_ftr);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000115 crypt_ftr.flags = props.Get<int>(tag::flags);
116 crypt_ftr.crypt_type = props.Get<int>(tag::crypt_type);
117 crypt_ftr.failed_decrypt_count = props.Get<int>(tag::failed_decrypt_count);
118 std::string crypto_type_name = props.Get<std::string>(tag::crypto_type_name);
119 strlcpy(reinterpret_cast<char*>(crypt_ftr.crypto_type_name),
120 crypto_type_name.c_str(),
121 sizeof(crypt_ftr.crypto_type_name));
122 std::string master_key = props.Get<std::string>(tag::master_key);
123 crypt_ftr.keysize = master_key.size();
124 if (crypt_ftr.keysize > sizeof(crypt_ftr.master_key)) {
125 SLOGE("Master key size too long");
126 return -1;
127 }
128 memcpy(crypt_ftr.master_key, &master_key[0], crypt_ftr.keysize);
129 std::string salt = props.Get<std::string>(tag::salt);
130 if (salt.size() != SALT_LEN) {
131 SLOGE("Salt wrong length");
132 return -1;
133 }
134 memcpy(crypt_ftr.salt, &salt[0], SALT_LEN);
135 crypt_ftr.kdf_type = props.Get<int>(tag::kdf_type);
136 crypt_ftr.N_factor = props.Get<int>(tag::N_factor);
137 crypt_ftr.r_factor = props.Get<int>(tag::r_factor);
138 crypt_ftr.p_factor = props.Get<int>(tag::p_factor);
139 std::string keymaster_blob = props.Get<std::string>(tag::keymaster_blob);
140 crypt_ftr.keymaster_blob_size = keymaster_blob.size();
141 if (crypt_ftr.keymaster_blob_size > sizeof(crypt_ftr.keymaster_blob)) {
142 SLOGE("Keymaster blob too long");
143 return -1;
144 }
145 memcpy(crypt_ftr.keymaster_blob, &keymaster_blob[0],
146 crypt_ftr.keymaster_blob_size);
147 std::string scrypted_intermediate_key = props.Get<std::string>(tag::scrypted_intermediate_key);
148 if (scrypted_intermediate_key.size() != SCRYPT_LEN) {
149 SLOGE("scrypted intermediate key wrong length");
150 return -1;
151 }
152 memcpy(crypt_ftr.scrypted_intermediate_key, &scrypted_intermediate_key[0],
153 SCRYPT_LEN);
154
155 return 0;
156}
157
158static UnencryptedProperties GetProps(const char* path)
159{
160 return UnencryptedProperties(path);
161}
162
163static UnencryptedProperties GetAltProps(const char* path)
164{
165 return UnencryptedProperties((std::string() + path + "/tmp_mnt").c_str());
166}
167
168static UnencryptedProperties GetPropsOrAltProps(const char* path)
169{
170 UnencryptedProperties props = GetProps(path);
171 if (props.OK()) {
172 return props;
173 }
174 return GetAltProps(path);
175}
176
177int e4crypt_enable(const char* path)
178{
179 // Already enabled?
180 if (s_key_store.find(path) != s_key_store.end()) {
181 return 0;
182 }
183
184 // Not an encryptable device?
185 UnencryptedProperties key_props = GetProps(path).GetChild(properties::key);
186 if (!key_props.OK()) {
187 return 0;
188 }
189
190 if (key_props.Get<std::string>(tag::master_key).empty()) {
191 crypt_mnt_ftr ftr;
192 if (cryptfs_create_default_ftr(&ftr, key_length)) {
193 SLOGE("Failed to create crypto footer");
194 return -1;
195 }
196
Paul Lawrence75c922f2015-05-05 15:58:27 -0700197 // Scrub fields not used by ext4enc
198 ftr.persist_data_offset[0] = 0;
199 ftr.persist_data_offset[1] = 0;
200 ftr.persist_data_size = 0;
201
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000202 if (put_crypt_ftr_and_key(ftr, key_props)) {
203 SLOGE("Failed to write crypto footer");
204 return -1;
205 }
206
207 crypt_mnt_ftr ftr2;
208 if (get_crypt_ftr_and_key(ftr2, key_props)) {
209 SLOGE("Failed to read crypto footer back");
210 return -1;
211 }
212
213 if (memcmp(&ftr, &ftr2, sizeof(ftr)) != 0) {
214 SLOGE("Crypto footer not correctly written");
Paul Lawrence75c922f2015-05-05 15:58:27 -0700215 return -1;
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000216 }
217 }
218
219 if (!UnencryptedProperties(path).Remove(properties::ref)) {
220 SLOGE("Failed to remove key ref");
221 return -1;
222 }
223
224 return e4crypt_check_passwd(path, "");
225}
226
227int e4crypt_change_password(const char* path, int crypt_type,
228 const char* password)
229{
230 SLOGI("e4crypt_change_password");
Paul Lawrenceaaccfac2015-05-04 15:48:24 -0700231 auto key_props = GetProps(path).GetChild(properties::key);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000232
233 crypt_mnt_ftr ftr;
234 if (get_crypt_ftr_and_key(ftr, key_props)) {
235 SLOGE("Failed to read crypto footer back");
236 return -1;
237 }
238
239 auto mki = s_key_store.find(path);
240 if (mki == s_key_store.end()) {
241 SLOGE("No stored master key - can't change password");
242 return -1;
243 }
244
245 const unsigned char* master_key
246 = reinterpret_cast<const unsigned char*>(&mki->second.master_key[0]);
247
248 if (cryptfs_set_password(&ftr, password, master_key)) {
249 SLOGE("Failed to set password");
250 return -1;
251 }
252
253 ftr.crypt_type = crypt_type;
254
255 if (put_crypt_ftr_and_key(ftr, key_props)) {
256 SLOGE("Failed to write crypto footer");
257 return -1;
258 }
259
260 if (!UnencryptedProperties(path).Set(properties::is_default,
261 crypt_type == CRYPT_TYPE_DEFAULT)) {
262 SLOGE("Failed to update default flag");
263 return -1;
264 }
265
266 return 0;
267}
268
269int e4crypt_crypto_complete(const char* path)
270{
271 SLOGI("ext4 crypto complete called on %s", path);
Paul Lawrenceaaccfac2015-05-04 15:48:24 -0700272 auto key_props = GetPropsOrAltProps(path).GetChild(properties::key);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000273 if (key_props.Get<std::string>(tag::master_key).empty()) {
274 SLOGI("No master key, so not ext4enc");
275 return -1;
276 }
277
278 return 0;
279}
280
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700281static std::string generate_key_ref(const char* key, int length)
282{
283 SHA512_CTX c;
284
285 SHA512_Init(&c);
286 SHA512_Update(&c, key, length);
287 unsigned char key_ref1[SHA512_LENGTH];
288 SHA512_Final(key_ref1, &c);
289
290 SHA512_Init(&c);
291 SHA512_Update(&c, key_ref1, SHA512_LENGTH);
292 unsigned char key_ref2[SHA512_LENGTH];
293 SHA512_Final(key_ref2, &c);
294
295 return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE);
296}
297
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000298int e4crypt_check_passwd(const char* path, const char* password)
299{
300 SLOGI("e4crypt_check_password");
Paul Lawrenceaaccfac2015-05-04 15:48:24 -0700301 auto props = GetPropsOrAltProps(path);
302 auto key_props = props.GetChild(properties::key);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000303
304 crypt_mnt_ftr ftr;
305 if (get_crypt_ftr_and_key(ftr, key_props)) {
306 SLOGE("Failed to read crypto footer back");
307 return -1;
308 }
309
310 unsigned char master_key[key_length / 8];
311 if (cryptfs_get_master_key (&ftr, password, master_key)){
312 SLOGI("Incorrect password");
Paul Lawrence3ca21e22015-04-14 15:26:29 -0700313 ftr.failed_decrypt_count++;
314 if (put_crypt_ftr_and_key(ftr, key_props)) {
315 SLOGW("Failed to update failed_decrypt_count");
316 }
317 return ftr.failed_decrypt_count;
318 }
319
320 if (ftr.failed_decrypt_count) {
321 ftr.failed_decrypt_count = 0;
322 if (put_crypt_ftr_and_key(ftr, key_props)) {
323 SLOGW("Failed to reset failed_decrypt_count");
324 }
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000325 }
326
Paul Lawrence00f4aad2015-05-06 13:53:43 -0700327 struct timespec now;
328 clock_gettime(CLOCK_BOOTTIME, &now);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000329 s_key_store[path] = keys{std::string(reinterpret_cast<char*>(master_key),
330 sizeof(master_key)),
Paul Lawrence00f4aad2015-05-06 13:53:43 -0700331 password,
332 now.tv_sec + password_max_age_seconds};
Paul Crowley1da96dc2015-05-06 13:38:53 +0100333 auto raw_ref = e4crypt_install_key(master_key);
334 if (raw_ref.empty()) {
335 return -1;
336 }
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000337
Paul Crowley1da96dc2015-05-06 13:38:53 +0100338 // Save reference to key so we can set policy later
339 if (!props.Set(properties::ref, raw_ref)) {
340 SLOGE("Cannot save key reference");
341 return -1;
342 }
343
344 return 0;
345}
346
347// Install password into global keyring
348// Return raw key reference for use in policy
349static std::string e4crypt_install_key(const unsigned char *key_bytes)
350{
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700351 // ext4enc:TODO Currently raw key is required to be of length
352 // sizeof(ext4_key.raw) == EXT4_MAX_KEY_SIZE, so zero pad to
353 // this length. Change when kernel bug is fixed.
354 ext4_encryption_key ext4_key = {EXT4_ENCRYPTION_MODE_AES_256_XTS,
355 {0},
356 sizeof(ext4_key.raw)};
357 memset(ext4_key.raw, 0, sizeof(ext4_key.raw));
358 static_assert(key_length / 8 <= sizeof(ext4_key.raw),
359 "Key too long!");
Paul Crowley1da96dc2015-05-06 13:38:53 +0100360 memcpy(ext4_key.raw, key_bytes, key_length / 8);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000361
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700362 // Get raw keyref - used to make keyname and to pass to ioctl
363 auto raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size);
364
365 // Generate keyname
366 std::ostringstream o;
367 for (auto i = raw_ref.begin(); i != raw_ref.end(); ++i) {
368 o << std::hex << std::setw(2) << std::setfill('0') << (int)*i;
369 }
370 auto ref = std::string("ext4:") + o.str();
371
372 // Find existing keyring
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000373 key_serial_t device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING,
374 "keyring", "e4crypt", 0);
375
376 SLOGI("Found device_keyring - id is %d", device_keyring);
377
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700378 // Add key ...
379 key_serial_t key_id = add_key("logon", ref.c_str(),
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000380 (void*)&ext4_key, sizeof(ext4_key),
381 device_keyring);
382
383 if (key_id == -1) {
384 SLOGE("Failed to insert key into keyring with error %s",
385 strerror(errno));
Paul Crowley1da96dc2015-05-06 13:38:53 +0100386 return std::string();
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000387 }
388
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700389 SLOGI("Added key %d (%s) to keyring %d in process %d",
390 key_id, ref.c_str(), device_keyring, getpid());
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000391
Paul Crowley1da96dc2015-05-06 13:38:53 +0100392 return raw_ref;
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000393}
394
395int e4crypt_restart(const char* path)
396{
397 SLOGI("e4crypt_restart");
398
399 int rc = 0;
400
401 SLOGI("ext4 restart called on %s", path);
402 property_set("vold.decrypt", "trigger_reset_main");
403 SLOGI("Just asked init to shut down class main");
404 sleep(2);
405
406 std::string tmp_path = std::string() + path + "/tmp_mnt";
407
Paul Lawrence29b54aa2015-05-05 14:28:25 -0700408 rc = wait_and_unmount(tmp_path.c_str(), true);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000409 if (rc) {
410 SLOGE("umount %s failed with rc %d, msg %s",
411 tmp_path.c_str(), rc, strerror(errno));
412 return rc;
413 }
414
Paul Lawrence29b54aa2015-05-05 14:28:25 -0700415 rc = wait_and_unmount(path, true);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000416 if (rc) {
417 SLOGE("umount %s failed with rc %d, msg %s",
418 path, rc, strerror(errno));
419 return rc;
420 }
421
422 return 0;
423}
424
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000425int e4crypt_get_password_type(const char* path)
426{
427 SLOGI("e4crypt_get_password_type");
428 return GetPropsOrAltProps(path).GetChild(properties::key)
429 .Get<int>(tag::crypt_type, CRYPT_TYPE_DEFAULT);
430}
Paul Lawrence4e727452015-04-15 14:12:00 -0700431
Paul Lawrence00f4aad2015-05-06 13:53:43 -0700432const char* e4crypt_get_password(const char* path)
433{
434 SLOGI("e4crypt_get_password");
435
436 auto i = s_key_store.find(path);
437 if (i == s_key_store.end()) {
438 return 0;
439 }
440
441 struct timespec now;
442 clock_gettime(CLOCK_BOOTTIME, &now);
443 if (i->second.expiry_time < now.tv_sec) {
444 e4crypt_clear_password(path);
445 return 0;
446 }
447
448 return i->second.password.c_str();
449}
450
451void e4crypt_clear_password(const char* path)
452{
453 SLOGI("e4crypt_clear_password");
454
455 auto i = s_key_store.find(path);
456 if (i == s_key_store.end()) {
457 return;
458 }
459
460 memset(&i->second.password[0], 0, i->second.password.size());
461 i->second.password = std::string();
462}
463
Paul Lawrence4e727452015-04-15 14:12:00 -0700464int e4crypt_get_field(const char* path, const char* fieldname,
465 char* value, size_t len)
466{
467 auto v = GetPropsOrAltProps(path).GetChild(properties::props)
468 .Get<std::string>(fieldname);
469
470 if (v == "") {
471 return CRYPTO_GETFIELD_ERROR_NO_FIELD;
472 }
473
474 if (v.length() >= len) {
475 return CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
476 }
477
478 strlcpy(value, v.c_str(), len);
479 return 0;
480}
481
482int e4crypt_set_field(const char* path, const char* fieldname,
483 const char* value)
484{
485 return GetPropsOrAltProps(path).GetChild(properties::props)
486 .Set(fieldname, std::string(value)) ? 0 : -1;
487}