blob: d200ca6c71d5da573f4a081a10d10149eb902b4f [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
72static int put_crypt_ftr_and_key(const crypt_mnt_ftr& crypt_ftr,
73 UnencryptedProperties& props)
74{
75 SLOGI("Putting crypt footer");
76
77 bool success = props.Set<int>(tag::magic, crypt_ftr.magic)
78 && props.Set<int>(tag::major_version, crypt_ftr.major_version)
79 && props.Set<int>(tag::minor_version, crypt_ftr.minor_version)
80 && props.Set<int>(tag::flags, crypt_ftr.flags)
81 && props.Set<int>(tag::crypt_type, crypt_ftr.crypt_type)
82 && props.Set<int>(tag::failed_decrypt_count,
83 crypt_ftr.failed_decrypt_count)
84 && props.Set<std::string>(tag::crypto_type_name,
85 std::string(reinterpret_cast<const char*>(crypt_ftr.crypto_type_name)))
86 && props.Set<std::string>(tag::master_key,
87 std::string((const char*) crypt_ftr.master_key,
88 crypt_ftr.keysize))
89 && props.Set<std::string>(tag::salt,
90 std::string((const char*) crypt_ftr.salt,
91 SALT_LEN))
92 && props.Set<int>(tag::kdf_type, crypt_ftr.kdf_type)
93 && props.Set<int>(tag::N_factor, crypt_ftr.N_factor)
94 && props.Set<int>(tag::r_factor, crypt_ftr.r_factor)
95 && props.Set<int>(tag::p_factor, crypt_ftr.p_factor)
96 && props.Set<std::string>(tag::keymaster_blob,
97 std::string((const char*) crypt_ftr.keymaster_blob,
98 crypt_ftr.keymaster_blob_size))
99 && props.Set<std::string>(tag::scrypted_intermediate_key,
100 std::string((const char*) crypt_ftr.scrypted_intermediate_key,
101 SCRYPT_LEN));
102 return success ? 0 : -1;
103}
104
105static int get_crypt_ftr_and_key(crypt_mnt_ftr& crypt_ftr,
106 const UnencryptedProperties& props)
107{
108 memset(&crypt_ftr, 0, sizeof(crypt_ftr));
109 crypt_ftr.magic = props.Get<int>(tag::magic);
110 crypt_ftr.major_version = props.Get<int>(tag::major_version);
111 crypt_ftr.minor_version = props.Get<int>(tag::minor_version);
Paul Lawrence75c922f2015-05-05 15:58:27 -0700112 crypt_ftr.ftr_size = sizeof(crypt_ftr);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000113 crypt_ftr.flags = props.Get<int>(tag::flags);
114 crypt_ftr.crypt_type = props.Get<int>(tag::crypt_type);
115 crypt_ftr.failed_decrypt_count = props.Get<int>(tag::failed_decrypt_count);
116 std::string crypto_type_name = props.Get<std::string>(tag::crypto_type_name);
117 strlcpy(reinterpret_cast<char*>(crypt_ftr.crypto_type_name),
118 crypto_type_name.c_str(),
119 sizeof(crypt_ftr.crypto_type_name));
120 std::string master_key = props.Get<std::string>(tag::master_key);
121 crypt_ftr.keysize = master_key.size();
122 if (crypt_ftr.keysize > sizeof(crypt_ftr.master_key)) {
123 SLOGE("Master key size too long");
124 return -1;
125 }
126 memcpy(crypt_ftr.master_key, &master_key[0], crypt_ftr.keysize);
127 std::string salt = props.Get<std::string>(tag::salt);
128 if (salt.size() != SALT_LEN) {
129 SLOGE("Salt wrong length");
130 return -1;
131 }
132 memcpy(crypt_ftr.salt, &salt[0], SALT_LEN);
133 crypt_ftr.kdf_type = props.Get<int>(tag::kdf_type);
134 crypt_ftr.N_factor = props.Get<int>(tag::N_factor);
135 crypt_ftr.r_factor = props.Get<int>(tag::r_factor);
136 crypt_ftr.p_factor = props.Get<int>(tag::p_factor);
137 std::string keymaster_blob = props.Get<std::string>(tag::keymaster_blob);
138 crypt_ftr.keymaster_blob_size = keymaster_blob.size();
139 if (crypt_ftr.keymaster_blob_size > sizeof(crypt_ftr.keymaster_blob)) {
140 SLOGE("Keymaster blob too long");
141 return -1;
142 }
143 memcpy(crypt_ftr.keymaster_blob, &keymaster_blob[0],
144 crypt_ftr.keymaster_blob_size);
145 std::string scrypted_intermediate_key = props.Get<std::string>(tag::scrypted_intermediate_key);
146 if (scrypted_intermediate_key.size() != SCRYPT_LEN) {
147 SLOGE("scrypted intermediate key wrong length");
148 return -1;
149 }
150 memcpy(crypt_ftr.scrypted_intermediate_key, &scrypted_intermediate_key[0],
151 SCRYPT_LEN);
152
153 return 0;
154}
155
156static UnencryptedProperties GetProps(const char* path)
157{
158 return UnencryptedProperties(path);
159}
160
161static UnencryptedProperties GetAltProps(const char* path)
162{
163 return UnencryptedProperties((std::string() + path + "/tmp_mnt").c_str());
164}
165
166static UnencryptedProperties GetPropsOrAltProps(const char* path)
167{
168 UnencryptedProperties props = GetProps(path);
169 if (props.OK()) {
170 return props;
171 }
172 return GetAltProps(path);
173}
174
175int e4crypt_enable(const char* path)
176{
177 // Already enabled?
178 if (s_key_store.find(path) != s_key_store.end()) {
179 return 0;
180 }
181
182 // Not an encryptable device?
183 UnencryptedProperties key_props = GetProps(path).GetChild(properties::key);
184 if (!key_props.OK()) {
185 return 0;
186 }
187
188 if (key_props.Get<std::string>(tag::master_key).empty()) {
189 crypt_mnt_ftr ftr;
190 if (cryptfs_create_default_ftr(&ftr, key_length)) {
191 SLOGE("Failed to create crypto footer");
192 return -1;
193 }
194
Paul Lawrence75c922f2015-05-05 15:58:27 -0700195 // Scrub fields not used by ext4enc
196 ftr.persist_data_offset[0] = 0;
197 ftr.persist_data_offset[1] = 0;
198 ftr.persist_data_size = 0;
199
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000200 if (put_crypt_ftr_and_key(ftr, key_props)) {
201 SLOGE("Failed to write crypto footer");
202 return -1;
203 }
204
205 crypt_mnt_ftr ftr2;
206 if (get_crypt_ftr_and_key(ftr2, key_props)) {
207 SLOGE("Failed to read crypto footer back");
208 return -1;
209 }
210
211 if (memcmp(&ftr, &ftr2, sizeof(ftr)) != 0) {
212 SLOGE("Crypto footer not correctly written");
Paul Lawrence75c922f2015-05-05 15:58:27 -0700213 return -1;
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000214 }
215 }
216
217 if (!UnencryptedProperties(path).Remove(properties::ref)) {
218 SLOGE("Failed to remove key ref");
219 return -1;
220 }
221
222 return e4crypt_check_passwd(path, "");
223}
224
225int e4crypt_change_password(const char* path, int crypt_type,
226 const char* password)
227{
228 SLOGI("e4crypt_change_password");
Paul Lawrenceaaccfac2015-05-04 15:48:24 -0700229 auto key_props = GetProps(path).GetChild(properties::key);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000230
231 crypt_mnt_ftr ftr;
232 if (get_crypt_ftr_and_key(ftr, key_props)) {
233 SLOGE("Failed to read crypto footer back");
234 return -1;
235 }
236
237 auto mki = s_key_store.find(path);
238 if (mki == s_key_store.end()) {
239 SLOGE("No stored master key - can't change password");
240 return -1;
241 }
242
243 const unsigned char* master_key
244 = reinterpret_cast<const unsigned char*>(&mki->second.master_key[0]);
245
246 if (cryptfs_set_password(&ftr, password, master_key)) {
247 SLOGE("Failed to set password");
248 return -1;
249 }
250
251 ftr.crypt_type = crypt_type;
252
253 if (put_crypt_ftr_and_key(ftr, key_props)) {
254 SLOGE("Failed to write crypto footer");
255 return -1;
256 }
257
258 if (!UnencryptedProperties(path).Set(properties::is_default,
259 crypt_type == CRYPT_TYPE_DEFAULT)) {
260 SLOGE("Failed to update default flag");
261 return -1;
262 }
263
264 return 0;
265}
266
267int e4crypt_crypto_complete(const char* path)
268{
269 SLOGI("ext4 crypto complete called on %s", path);
Paul Lawrenceaaccfac2015-05-04 15:48:24 -0700270 auto key_props = GetPropsOrAltProps(path).GetChild(properties::key);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000271 if (key_props.Get<std::string>(tag::master_key).empty()) {
272 SLOGI("No master key, so not ext4enc");
273 return -1;
274 }
275
276 return 0;
277}
278
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700279static std::string generate_key_ref(const char* key, int length)
280{
281 SHA512_CTX c;
282
283 SHA512_Init(&c);
284 SHA512_Update(&c, key, length);
285 unsigned char key_ref1[SHA512_LENGTH];
286 SHA512_Final(key_ref1, &c);
287
288 SHA512_Init(&c);
289 SHA512_Update(&c, key_ref1, SHA512_LENGTH);
290 unsigned char key_ref2[SHA512_LENGTH];
291 SHA512_Final(key_ref2, &c);
292
293 return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE);
294}
295
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000296int e4crypt_check_passwd(const char* path, const char* password)
297{
298 SLOGI("e4crypt_check_password");
Paul Lawrenceaaccfac2015-05-04 15:48:24 -0700299 auto props = GetPropsOrAltProps(path);
300 auto key_props = props.GetChild(properties::key);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000301
302 crypt_mnt_ftr ftr;
303 if (get_crypt_ftr_and_key(ftr, key_props)) {
304 SLOGE("Failed to read crypto footer back");
305 return -1;
306 }
307
308 unsigned char master_key[key_length / 8];
309 if (cryptfs_get_master_key (&ftr, password, master_key)){
310 SLOGI("Incorrect password");
Paul Lawrence3ca21e22015-04-14 15:26:29 -0700311 ftr.failed_decrypt_count++;
312 if (put_crypt_ftr_and_key(ftr, key_props)) {
313 SLOGW("Failed to update failed_decrypt_count");
314 }
315 return ftr.failed_decrypt_count;
316 }
317
318 if (ftr.failed_decrypt_count) {
319 ftr.failed_decrypt_count = 0;
320 if (put_crypt_ftr_and_key(ftr, key_props)) {
321 SLOGW("Failed to reset failed_decrypt_count");
322 }
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000323 }
324
Paul Lawrence00f4aad2015-05-06 13:53:43 -0700325 struct timespec now;
326 clock_gettime(CLOCK_BOOTTIME, &now);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000327 s_key_store[path] = keys{std::string(reinterpret_cast<char*>(master_key),
328 sizeof(master_key)),
Paul Lawrence00f4aad2015-05-06 13:53:43 -0700329 password,
330 now.tv_sec + password_max_age_seconds};
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000331
332 // Install password into global keyring
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700333 // ext4enc:TODO Currently raw key is required to be of length
334 // sizeof(ext4_key.raw) == EXT4_MAX_KEY_SIZE, so zero pad to
335 // this length. Change when kernel bug is fixed.
336 ext4_encryption_key ext4_key = {EXT4_ENCRYPTION_MODE_AES_256_XTS,
337 {0},
338 sizeof(ext4_key.raw)};
339 memset(ext4_key.raw, 0, sizeof(ext4_key.raw));
340 static_assert(key_length / 8 <= sizeof(ext4_key.raw),
341 "Key too long!");
342 memcpy(ext4_key.raw, master_key, key_length / 8);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000343
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700344 // Get raw keyref - used to make keyname and to pass to ioctl
345 auto raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size);
346
347 // Generate keyname
348 std::ostringstream o;
349 for (auto i = raw_ref.begin(); i != raw_ref.end(); ++i) {
350 o << std::hex << std::setw(2) << std::setfill('0') << (int)*i;
351 }
352 auto ref = std::string("ext4:") + o.str();
353
354 // Find existing keyring
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000355 key_serial_t device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING,
356 "keyring", "e4crypt", 0);
357
358 SLOGI("Found device_keyring - id is %d", device_keyring);
359
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700360 // Add key ...
361 key_serial_t key_id = add_key("logon", ref.c_str(),
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000362 (void*)&ext4_key, sizeof(ext4_key),
363 device_keyring);
364
365 if (key_id == -1) {
366 SLOGE("Failed to insert key into keyring with error %s",
367 strerror(errno));
368 return -1;
369 }
370
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700371 SLOGI("Added key %d (%s) to keyring %d in process %d",
372 key_id, ref.c_str(), device_keyring, getpid());
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000373
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000374 // Save reference to key so we can set policy later
Paul Lawrence5e7f0042015-04-10 07:48:51 -0700375 if (!props.Set(properties::ref, raw_ref)) {
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000376 SLOGE("Cannot save key reference");
377 return -1;
378 }
379
380 return 0;
381}
382
383int e4crypt_restart(const char* path)
384{
385 SLOGI("e4crypt_restart");
386
387 int rc = 0;
388
389 SLOGI("ext4 restart called on %s", path);
390 property_set("vold.decrypt", "trigger_reset_main");
391 SLOGI("Just asked init to shut down class main");
392 sleep(2);
393
394 std::string tmp_path = std::string() + path + "/tmp_mnt";
395
Paul Lawrence29b54aa2015-05-05 14:28:25 -0700396 rc = wait_and_unmount(tmp_path.c_str(), true);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000397 if (rc) {
398 SLOGE("umount %s failed with rc %d, msg %s",
399 tmp_path.c_str(), rc, strerror(errno));
400 return rc;
401 }
402
Paul Lawrence29b54aa2015-05-05 14:28:25 -0700403 rc = wait_and_unmount(path, true);
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000404 if (rc) {
405 SLOGE("umount %s failed with rc %d, msg %s",
406 path, rc, strerror(errno));
407 return rc;
408 }
409
410 return 0;
411}
412
Paul Lawrence707fd6c2015-04-28 22:14:15 +0000413int e4crypt_get_password_type(const char* path)
414{
415 SLOGI("e4crypt_get_password_type");
416 return GetPropsOrAltProps(path).GetChild(properties::key)
417 .Get<int>(tag::crypt_type, CRYPT_TYPE_DEFAULT);
418}
Paul Lawrence4e727452015-04-15 14:12:00 -0700419
Paul Lawrence00f4aad2015-05-06 13:53:43 -0700420const char* e4crypt_get_password(const char* path)
421{
422 SLOGI("e4crypt_get_password");
423
424 auto i = s_key_store.find(path);
425 if (i == s_key_store.end()) {
426 return 0;
427 }
428
429 struct timespec now;
430 clock_gettime(CLOCK_BOOTTIME, &now);
431 if (i->second.expiry_time < now.tv_sec) {
432 e4crypt_clear_password(path);
433 return 0;
434 }
435
436 return i->second.password.c_str();
437}
438
439void e4crypt_clear_password(const char* path)
440{
441 SLOGI("e4crypt_clear_password");
442
443 auto i = s_key_store.find(path);
444 if (i == s_key_store.end()) {
445 return;
446 }
447
448 memset(&i->second.password[0], 0, i->second.password.size());
449 i->second.password = std::string();
450}
451
Paul Lawrence4e727452015-04-15 14:12:00 -0700452int e4crypt_get_field(const char* path, const char* fieldname,
453 char* value, size_t len)
454{
455 auto v = GetPropsOrAltProps(path).GetChild(properties::props)
456 .Get<std::string>(fieldname);
457
458 if (v == "") {
459 return CRYPTO_GETFIELD_ERROR_NO_FIELD;
460 }
461
462 if (v.length() >= len) {
463 return CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
464 }
465
466 strlcpy(value, v.c_str(), len);
467 return 0;
468}
469
470int e4crypt_set_field(const char* path, const char* fieldname,
471 const char* value)
472{
473 return GetPropsOrAltProps(path).GetChild(properties::props)
474 .Set(fieldname, std::string(value)) ? 0 : -1;
475}