18f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall/*
28f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * Copyright (C) 2010 The Android Open Source Project
38f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall *
48f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * Licensed under the Apache License, Version 2.0 (the "License");
58f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * you may not use this file except in compliance with the License.
68f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * You may obtain a copy of the License at
78f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall *
88f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall *      http://www.apache.org/licenses/LICENSE-2.0
98f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall *
108f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * Unless required by applicable law or agreed to in writing, software
118f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * distributed under the License is distributed on an "AS IS" BASIS,
128f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * See the License for the specific language governing permissions and
148f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * limitations under the License.
158f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall */
168f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
178f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall/* TO DO:
188f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall *   1.  Perhaps keep several copies of the encrypted key, in case something
198f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall *       goes horribly wrong?
208f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall *
218f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall */
228f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
238f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <sys/types.h>
24e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall#include <sys/wait.h>
258f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <sys/stat.h>
26f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence#include <ctype.h>
278f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <fcntl.h>
287373716c6d65ca328de11c994c60f698a9ef6290Elliott Hughes#include <inttypes.h>
298f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <unistd.h>
308f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <stdio.h>
318f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <sys/ioctl.h>
328f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <linux/dm-ioctl.h>
338f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <libgen.h>
348f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <stdlib.h>
358f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <sys/param.h>
368f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <string.h>
378f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <sys/mount.h>
388f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <openssl/evp.h>
3941405bb3e5cdde0782bfcf7065b88ce1bb253c3cAdam Langley#include <openssl/sha.h>
408f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include <errno.h>
415a95ddbacfe4ec74b6b90dd7a9bc76d27b173758Tao Bao#include <ext4_utils/ext4.h>
425a95ddbacfe4ec74b6b90dd7a9bc76d27b173758Tao Bao#include <ext4_utils/ext4_utils.h>
4329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include <linux/kdev_t.h>
44e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall#include <fs_mgr.h>
459c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence#include <time.h>
4685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu#include <math.h>
47df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep#include <selinux/selinux.h>
488f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include "cryptfs.h"
49df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep#include "secontext.h"
508f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#define LOG_TAG "Cryptfs"
518f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include "cutils/log.h"
528f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include "cutils/properties.h"
53adfba3626e76c1931649634275d241b226cd1b9aKen Sumrall#include "cutils/android_reboot.h"
545d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall#include "hardware_legacy/power.h"
55e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall#include <logwrap/logwrap.h>
5663c18d3ba9179ee0e678564e12aa845d9a6c3ec8Paul Crowley#include "ScryptParameters.h"
5729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "VolumeManager.h"
589caab76c6b5aefdeeb1715a3695491ca793b8c18Ken Sumrall#include "VoldUtil.h"
59731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "Ext4Crypt.h"
60e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg#include "f2fs_sparseblock.h"
6187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence#include "CheckBattery.h"
623f14fe45a3e7bc0d12ba26d20a36d355a10f623ejessica_yu#include "Process.h"
63015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis#include "Keymaster.h"
644375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang#include "android-base/properties.h"
651fb5966fbb4e05d15cb10ff371137b4ef9dff584Yabin Cui#include <bootloader_message/bootloader_message.h>
664375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wangextern "C" {
674375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang#include <crypto_scrypt.h>
684375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang}
693e971277db0d87652af5622c989233e7159ab909Mark Salyzyn
705eecc449cc75771cc0c6eb0ad936117d16704b83Mark Salyzyn#define UNUSED __attribute__((unused))
715eecc449cc75771cc0c6eb0ad936117d16704b83Mark Salyzyn
728f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#define DM_CRYPT_BUF_SIZE 4096
738f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
7470a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks#define HASH_COUNT 2000
7570a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks#define KEY_LEN_BYTES 16
7670a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks#define IV_LEN_BYTES 16
7770a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks
7829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#define KEY_IN_FOOTER  "footer"
7929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
803bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence#define DEFAULT_PASSWORD "default_password"
81f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
823d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence#define CRYPTO_BLOCK_DEVICE "userdata"
833d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
843d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence#define BREADCRUMB_FILE "/data/misc/vold/convert_fde"
853d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
8629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#define EXT4_FS 1
8762c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall#define F2FS_FS 2
8829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
89e919efea94b178ed214ed2e78ef0d008727d62abKen Sumrall#define TABLE_LOAD_RETRIES 10
90e919efea94b178ed214ed2e78ef0d008727d62abKen Sumrall
9147ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden#define RSA_KEY_SIZE 2048
9247ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden#define RSA_KEY_SIZE_BYTES (RSA_KEY_SIZE / 8)
9347ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden#define RSA_EXPONENT 0x10001
94da6e899f4e1429add2ef023e0cc6b0fcca42c945Shawn Willden#define KEYMASTER_CRYPTFS_RATE_LIMIT 1  // Maximum one try per second
9569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
968e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence#define RETRY_MOUNT_ATTEMPTS 10
978e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence#define RETRY_MOUNT_DELAY_SECONDS 1
988e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence
9970a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parksstatic unsigned char saved_master_key[KEY_LEN_BYTES];
1003ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrallstatic char *saved_mount_point;
10170a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parksstatic int  master_key_saved = 0;
102160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic struct crypt_persist_data *persist_data = NULL;
10356ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall
10469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence/* Should we use keymaster? */
10569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrencestatic int keymaster_check_compatibility()
10669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence{
107015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis    return keymaster_compatibility_cryptfs_scrypt();
10869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence}
10969f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
11069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence/* Create a new keymaster key and store it in this footer */
11169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrencestatic int keymaster_create_key(struct crypt_mnt_ftr *ftr)
11269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence{
1133d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (ftr->keymaster_blob_size) {
1143d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        SLOGI("Already have key");
1153d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        return 0;
1163d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    }
1173d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
118015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis    int rc = keymaster_create_key_for_cryptfs_scrypt(RSA_KEY_SIZE, RSA_EXPONENT,
119015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis            KEYMASTER_CRYPTFS_RATE_LIMIT, ftr->keymaster_blob, KEYMASTER_BLOB_SIZE,
120015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis            &ftr->keymaster_blob_size);
121015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis    if (rc) {
122015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis        if (ftr->keymaster_blob_size > KEYMASTER_BLOB_SIZE) {
123015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis            SLOGE("Keymaster key blob to large)");
124015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis            ftr->keymaster_blob_size = 0;
125cfc5202147a1f72a61415266f0d4097544ce8b89Alex Klyubin        }
126015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis        SLOGE("Failed to generate keypair");
127015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis        return -1;
128cfc5202147a1f72a61415266f0d4097544ce8b89Alex Klyubin    }
129015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis    return 0;
13069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence}
13169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
132e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden/* This signs the given object using the keymaster key. */
133e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willdenstatic int keymaster_sign_object(struct crypt_mnt_ftr *ftr,
13447ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden                                 const unsigned char *object,
13547ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden                                 const size_t object_size,
13647ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden                                 unsigned char **signature,
13747ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden                                 size_t *signature_size)
13847ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden{
13947ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden    unsigned char to_sign[RSA_KEY_SIZE_BYTES];
140e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    size_t to_sign_size = sizeof(to_sign);
14147ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden    memset(to_sign, 0, RSA_KEY_SIZE_BYTES);
14247ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden
143e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    // To sign a message with RSA, the message must satisfy two
144e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    // constraints:
145e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //
146e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    // 1. The message, when interpreted as a big-endian numeric value, must
147e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //    be strictly less than the public modulus of the RSA key.  Note
148e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //    that because the most significant bit of the public modulus is
149e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //    guaranteed to be 1 (else it's an (n-1)-bit key, not an n-bit
150e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //    key), an n-bit message with most significant bit 0 always
151e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //    satisfies this requirement.
152e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //
153e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    // 2. The message must have the same length in bits as the public
154e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //    modulus of the RSA key.  This requirement isn't mathematically
155e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //    necessary, but is necessary to ensure consistency in
156e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    //    implementations.
157e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    switch (ftr->kdf_type) {
158e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden        case KDF_SCRYPT_KEYMASTER:
159e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden            // This ensures the most significant byte of the signed message
160e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden            // is zero.  We could have zero-padded to the left instead, but
161e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden            // this approach is slightly more robust against changes in
162e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden            // object size.  However, it's still broken (but not unusably
163da6e899f4e1429add2ef023e0cc6b0fcca42c945Shawn Willden            // so) because we really should be using a proper deterministic
164da6e899f4e1429add2ef023e0cc6b0fcca42c945Shawn Willden            // RSA padding function, such as PKCS1.
1654375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang            memcpy(to_sign + 1, object, std::min((size_t)RSA_KEY_SIZE_BYTES - 1, object_size));
166e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden            SLOGI("Signing safely-padded object");
167e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden            break;
168e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden        default:
169e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden            SLOGE("Unknown KDF type %d", ftr->kdf_type);
170015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis            return -1;
171da6e899f4e1429add2ef023e0cc6b0fcca42c945Shawn Willden    }
172015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis    return keymaster_sign_object_for_cryptfs_scrypt(ftr->keymaster_blob, ftr->keymaster_blob_size,
173015ec30b36713308db9f0051e8f97338419d7fbfJanis Danisevskis            KEYMASTER_CRYPTFS_RATE_LIMIT, to_sign, to_sign_size, signature, signature_size);
17447ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden}
17547ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden
176399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence/* Store password when userdata is successfully decrypted and mounted.
177399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence * Cleared by cryptfs_clear_password
178399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence *
179399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence * To avoid a double prompt at boot, we need to store the CryptKeeper
180399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence * password and pass it to KeyGuard, which uses it to unlock KeyStore.
181399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence * Since the entire framework is torn down and rebuilt after encryption,
182399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence * we have to use a daemon or similar to store the password. Since vold
183399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence * is secured against IPC except from system processes, it seems a reasonable
184399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence * place to store this.
185399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence *
186399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence * password should be cleared once it has been used.
187399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence *
188399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence * password is aged out after password_max_age_seconds seconds.
189684dbdf316a02cf6a7694018f7c3a4bcd65142ccPaul Lawrence */
190399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrencestatic char* password = 0;
191399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrencestatic int password_expiry_time = 0;
192399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrencestatic const int password_max_age_seconds = 60;
193684dbdf316a02cf6a7694018f7c3a4bcd65142ccPaul Lawrence
19456ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrallextern struct fstab *fstab;
1958ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
19687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrenceenum RebootType {reboot, recovery, shutdown};
19787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrencestatic void cryptfs_reboot(enum RebootType rt)
198adfba3626e76c1931649634275d241b226cd1b9aKen Sumrall{
19987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence  switch(rt) {
20087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence      case reboot:
20187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence          property_set(ANDROID_RB_PROPERTY, "reboot");
20287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence          break;
20387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
20487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence      case recovery:
20587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence          property_set(ANDROID_RB_PROPERTY, "reboot,recovery");
20687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence          break;
20787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
20887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence      case shutdown:
20987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence          property_set(ANDROID_RB_PROPERTY, "shutdown");
21087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence          break;
211adfba3626e76c1931649634275d241b226cd1b9aKen Sumrall    }
21287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
213adfba3626e76c1931649634275d241b226cd1b9aKen Sumrall    sleep(20);
214adfba3626e76c1931649634275d241b226cd1b9aKen Sumrall
215adfba3626e76c1931649634275d241b226cd1b9aKen Sumrall    /* Shouldn't get here, reboot should happen before sleep times out */
216adfba3626e76c1931649634275d241b226cd1b9aKen Sumrall    return;
217adfba3626e76c1931649634275d241b226cd1b9aKen Sumrall}
218adfba3626e76c1931649634275d241b226cd1b9aKen Sumrall
2198f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrallstatic void ioctl_init(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags)
2208f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
2218f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    memset(io, 0, dataSize);
2228f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    io->data_size = dataSize;
2238f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    io->data_start = sizeof(struct dm_ioctl);
2248f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    io->version[0] = 4;
2258f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    io->version[1] = 0;
2268f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    io->version[2] = 0;
2278f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    io->flags = flags;
2288f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    if (name) {
2295e6b9141c11ebfd809acb69c7c672c6612334359Marek Pola        strlcpy(io->name, name, sizeof(io->name));
2308f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
2318f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
2328f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
233c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root/**
234c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root * Gets the default device scrypt parameters for key derivation time tuning.
235c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root * The parameters should lead to about one second derivation time for the
236c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root * given device.
237c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root */
238c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Rootstatic void get_device_scrypt_params(struct crypt_mnt_ftr *ftr) {
239c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    char paramstr[PROPERTY_VALUE_MAX];
24063c18d3ba9179ee0e678564e12aa845d9a6c3ec8Paul Crowley    int Nf, rf, pf;
241c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
24263c18d3ba9179ee0e678564e12aa845d9a6c3ec8Paul Crowley    property_get(SCRYPT_PROP, paramstr, SCRYPT_DEFAULTS);
24363c18d3ba9179ee0e678564e12aa845d9a6c3ec8Paul Crowley    if (!parse_scrypt_parameters(paramstr, &Nf, &rf, &pf)) {
24463c18d3ba9179ee0e678564e12aa845d9a6c3ec8Paul Crowley        SLOGW("bad scrypt parameters '%s' should be like '12:8:1'; using defaults", paramstr);
24563c18d3ba9179ee0e678564e12aa845d9a6c3ec8Paul Crowley        parse_scrypt_parameters(SCRYPT_DEFAULTS, &Nf, &rf, &pf);
246c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    }
24763c18d3ba9179ee0e678564e12aa845d9a6c3ec8Paul Crowley    ftr->N_factor = Nf;
24863c18d3ba9179ee0e678564e12aa845d9a6c3ec8Paul Crowley    ftr->r_factor = rf;
24963c18d3ba9179ee0e678564e12aa845d9a6c3ec8Paul Crowley    ftr->p_factor = pf;
250c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root}
251c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
2523ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrallstatic unsigned int get_fs_size(char *dev)
2533ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall{
2543ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    int fd, block_size;
2553ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    struct ext4_super_block sb;
2563ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    off64_t len;
2573ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
258ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if ((fd = open(dev, O_RDONLY|O_CLOEXEC)) < 0) {
2593ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        SLOGE("Cannot open device to get filesystem size ");
2603ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        return 0;
2613ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    }
2623ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
2633ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    if (lseek64(fd, 1024, SEEK_SET) < 0) {
2643ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        SLOGE("Cannot seek to superblock");
2653ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        return 0;
2663ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    }
2673ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
2683ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
2693ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        SLOGE("Cannot read superblock");
2703ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        return 0;
2713ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    }
2723ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
2733ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    close(fd);
2743ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
275e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    if (le32_to_cpu(sb.s_magic) != EXT4_SUPER_MAGIC) {
276e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        SLOGE("Not a valid ext4 superblock");
277e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        return 0;
278e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    }
2793ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    block_size = 1024 << sb.s_log_block_size;
2803ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    /* compute length in bytes */
2813ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    len = ( ((off64_t)sb.s_blocks_count_hi << 32) + sb.s_blocks_count_lo) * block_size;
2823ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
2833ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    /* return length in sectors */
2843ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    return (unsigned int) (len / 512);
2853ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall}
2863ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
287160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic int get_crypt_ftr_info(char **metadata_fname, off64_t *off)
2888f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
289160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  static int cached_data = 0;
290160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  static off64_t cached_off = 0;
291160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  static char cached_metadata_fname[PROPERTY_VALUE_MAX] = "";
2928f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  int fd;
29329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall  char key_loc[PROPERTY_VALUE_MAX];
294160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  char real_blkdev[PROPERTY_VALUE_MAX];
295160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  int rc = -1;
2968f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
297160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (!cached_data) {
298160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    fs_mgr_get_crypt_info(fstab, key_loc, real_blkdev, sizeof(key_loc));
2998f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
300160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (!strcmp(key_loc, KEY_IN_FOOTER)) {
301ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey      if ( (fd = open(real_blkdev, O_RDWR|O_CLOEXEC)) < 0) {
302160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Cannot open real block device %s\n", real_blkdev);
303160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
304160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall      }
3058f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
30614eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa      unsigned long nr_sec = 0;
30714eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa      get_blkdev_size(fd, &nr_sec);
30814eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa      if (nr_sec != 0) {
309160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        /* If it's an encrypted Android partition, the last 16 Kbytes contain the
310160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall         * encryption info footer and key, and plenty of bytes to spare for future
311160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall         * growth.
312160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall         */
313160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        strlcpy(cached_metadata_fname, real_blkdev, sizeof(cached_metadata_fname));
314160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        cached_off = ((off64_t)nr_sec * 512) - CRYPT_FOOTER_OFFSET;
315160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        cached_data = 1;
316160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall      } else {
317160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Cannot get size of block device %s\n", real_blkdev);
318160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall      }
319160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall      close(fd);
320160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    } else {
321160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall      strlcpy(cached_metadata_fname, key_loc, sizeof(cached_metadata_fname));
322160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall      cached_off = 0;
323160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall      cached_data = 1;
32429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
325160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  }
3268f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
327160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (cached_data) {
328160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (metadata_fname) {
329160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        *metadata_fname = cached_metadata_fname;
33029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
331160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (off) {
332160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        *off = cached_off;
33329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
334160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    rc = 0;
3358f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
3368f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
337160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  return rc;
338160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
3398f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
3403d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence/* Set sha256 checksum in structure */
3413d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrencestatic void set_ftr_sha(struct crypt_mnt_ftr *crypt_ftr)
3423d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence{
3433d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    SHA256_CTX c;
3443d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    SHA256_Init(&c);
3453d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    memset(crypt_ftr->sha256, 0, sizeof(crypt_ftr->sha256));
3463d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    SHA256_Update(&c, crypt_ftr, sizeof(*crypt_ftr));
3473d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    SHA256_Final(crypt_ftr->sha256, &c);
3483d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence}
3493d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
350160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall/* key or salt can be NULL, in which case just skip writing that value.  Useful to
351160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall * update the failed mount count but not change the key.
352160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall */
353160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic int put_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr)
354160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
355160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  int fd;
3568439dc9fd569794b1a31f67cf43d9212de33eeccTim Murray  unsigned int cnt;
357160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  /* starting_off is set to the SEEK_SET offset
358160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall   * where the crypto structure starts
359160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall   */
360160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  off64_t starting_off;
361160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  int rc = -1;
362160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  char *fname = NULL;
363160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  struct stat statbuf;
3648f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
3653d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence  set_ftr_sha(crypt_ftr);
3663d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
367160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (get_crypt_ftr_info(&fname, &starting_off)) {
368160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    SLOGE("Unable to get crypt_ftr_info\n");
369160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
370160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  }
371160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (fname[0] != '/') {
372160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    SLOGE("Unexpected value for crypto key location\n");
373160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
374160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  }
375ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey  if ( (fd = open(fname, O_RDWR | O_CREAT|O_CLOEXEC, 0600)) < 0) {
376e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall    SLOGE("Cannot open footer file %s for put\n", fname);
377160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
3788f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
3798f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
380160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  /* Seek to the start of the crypt footer */
381160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (lseek64(fd, starting_off, SEEK_SET) == -1) {
382160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    SLOGE("Cannot seek to real block device footer\n");
383160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    goto errout;
384160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  }
385e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall
386160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if ((cnt = write(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr))) != sizeof(struct crypt_mnt_ftr)) {
387160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    SLOGE("Cannot write real block device footer\n");
388160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    goto errout;
38929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall  }
39029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
3913be890f59c04f94537f2f66f1d2841ed591f1a6eKen Sumrall  fstat(fd, &statbuf);
3923be890f59c04f94537f2f66f1d2841ed591f1a6eKen Sumrall  /* If the keys are kept on a raw block device, do not try to truncate it. */
393e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall  if (S_ISREG(statbuf.st_mode)) {
39429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    if (ftruncate(fd, 0x4000)) {
39559846b654e8b4a22a1be11cd21d6c5b81375abd2Colin Cross      SLOGE("Cannot set footer file size\n");
396e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall      goto errout;
397e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall    }
398e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall  }
399e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall
4008f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  /* Success! */
4018f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  rc = 0;
4028f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
4038f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrallerrout:
4048f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  close(fd);
4058f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  return rc;
4068f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
4078f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
4088f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
4093d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrencestatic bool check_ftr_sha(const struct crypt_mnt_ftr *crypt_ftr)
4103d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence{
4113d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    struct crypt_mnt_ftr copy;
4123d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    memcpy(&copy, crypt_ftr, sizeof(copy));
4133d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    set_ftr_sha(&copy);
4143d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    return memcmp(copy.sha256, crypt_ftr->sha256, sizeof(copy.sha256)) == 0;
4153d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence}
4163d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
417160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic inline int unix_read(int  fd, void*  buff, int  len)
4188f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
419160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return TEMP_FAILURE_RETRY(read(fd, buff, len));
420160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
4218f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
422160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic inline int unix_write(int  fd, const void*  buff, int  len)
423160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
424160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return TEMP_FAILURE_RETRY(write(fd, buff, len));
425160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
4268f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
427160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic void init_empty_persist_data(struct crypt_persist_data *pdata, int len)
428160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
429160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    memset(pdata, 0, len);
430160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    pdata->persist_magic = PERSIST_DATA_MAGIC;
431160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    pdata->persist_valid_entries = 0;
432160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
4338f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
434160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall/* A routine to update the passed in crypt_ftr to the lastest version.
435160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall * fd is open read/write on the device that holds the crypto footer and persistent
436160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall * data, crypt_ftr is a pointer to the struct to be updated, and offset is the
437160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall * absolute offset to the start of the crypt_mnt_ftr on the passed in fd.
438160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall */
439160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic void upgrade_crypt_ftr(int fd, struct crypt_mnt_ftr *crypt_ftr, off64_t offset)
440160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
4417434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root    int orig_major = crypt_ftr->major_version;
4427434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root    int orig_minor = crypt_ftr->minor_version;
4437434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root
4447434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root    if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 0)) {
4457434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        struct crypt_persist_data *pdata;
4467434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        off64_t pdata_offset = offset + CRYPT_FOOTER_TO_PERSIST_OFFSET;
4477434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root
448c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        SLOGW("upgrading crypto footer to 1.1");
449c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
4504375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang        pdata = (crypt_persist_data *)malloc(CRYPT_PERSIST_DATA_SIZE);
4517434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        if (pdata == NULL) {
4527434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root            SLOGE("Cannot allocate persisent data\n");
4537434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root            return;
4547434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        }
4557434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        memset(pdata, 0, CRYPT_PERSIST_DATA_SIZE);
4567434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root
4577434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        /* Need to initialize the persistent data area */
4587434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        if (lseek64(fd, pdata_offset, SEEK_SET) == -1) {
4597434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root            SLOGE("Cannot seek to persisent data offset\n");
46091064633ff3e5dd0a8a7d0c065cd82ba06b04aceHenrik Baard            free(pdata);
4617434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root            return;
4627434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        }
4637434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        /* Write all zeros to the first copy, making it invalid */
4647434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        unix_write(fd, pdata, CRYPT_PERSIST_DATA_SIZE);
4657434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root
4667434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        /* Write a valid but empty structure to the second copy */
4677434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        init_empty_persist_data(pdata, CRYPT_PERSIST_DATA_SIZE);
4687434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        unix_write(fd, pdata, CRYPT_PERSIST_DATA_SIZE);
4697434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root
4707434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        /* Update the footer */
4717434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        crypt_ftr->persist_data_size = CRYPT_PERSIST_DATA_SIZE;
4727434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        crypt_ftr->persist_data_offset[0] = pdata_offset;
4737434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        crypt_ftr->persist_data_offset[1] = pdata_offset + CRYPT_PERSIST_DATA_SIZE;
4747434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        crypt_ftr->minor_version = 1;
47591064633ff3e5dd0a8a7d0c065cd82ba06b04aceHenrik Baard        free(pdata);
47629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
477160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
478f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 1)) {
479c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        SLOGW("upgrading crypto footer to 1.2");
4807bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall        /* But keep the old kdf_type.
4817bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall         * It will get updated later to KDF_SCRYPT after the password has been verified.
4827bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall         */
483c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        crypt_ftr->kdf_type = KDF_PBKDF2;
484c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        get_device_scrypt_params(crypt_ftr);
485c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        crypt_ftr->minor_version = 2;
486c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    }
487c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
488f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 2)) {
489f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGW("upgrading crypto footer to 1.3");
490f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        crypt_ftr->crypt_type = CRYPT_TYPE_PASSWORD;
491f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        crypt_ftr->minor_version = 3;
492f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    }
493f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
4947434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root    if ((orig_major != crypt_ftr->major_version) || (orig_minor != crypt_ftr->minor_version)) {
4957434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        if (lseek64(fd, offset, SEEK_SET) == -1) {
4967434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root            SLOGE("Cannot seek to crypt footer\n");
4977434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root            return;
4987434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        }
4997434b3111b80d2b84ddf656b66b7bf6591de5ab6Kenny Root        unix_write(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr));
500160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
501160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
502160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
503160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
504160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic int get_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr)
505160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
506160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  int fd;
5078439dc9fd569794b1a31f67cf43d9212de33eeccTim Murray  unsigned int cnt;
508160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  off64_t starting_off;
509160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  int rc = -1;
510160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  char *fname = NULL;
511160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  struct stat statbuf;
512160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
513160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (get_crypt_ftr_info(&fname, &starting_off)) {
514160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    SLOGE("Unable to get crypt_ftr_info\n");
515160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
516160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  }
517160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (fname[0] != '/') {
518e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall    SLOGE("Unexpected value for crypto key location\n");
519160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
520160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  }
521ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey  if ( (fd = open(fname, O_RDWR|O_CLOEXEC)) < 0) {
522e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall    SLOGE("Cannot open footer file %s for get\n", fname);
523160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
524160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  }
525160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
526160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  /* Make sure it's 16 Kbytes in length */
527160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  fstat(fd, &statbuf);
528160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (S_ISREG(statbuf.st_mode) && (statbuf.st_size != 0x4000)) {
529160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    SLOGE("footer file %s is not the expected size!\n", fname);
530160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    goto errout;
531160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  }
532160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
533160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  /* Seek to the start of the crypt footer */
534160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (lseek64(fd, starting_off, SEEK_SET) == -1) {
535160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    SLOGE("Cannot seek to real block device footer\n");
536160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    goto errout;
5378f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
5388f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
5398f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  if ( (cnt = read(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr))) != sizeof(struct crypt_mnt_ftr)) {
5408f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    SLOGE("Cannot read real block device footer\n");
5418f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    goto errout;
5428f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
5438f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
5448f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  if (crypt_ftr->magic != CRYPT_MNT_MAGIC) {
54529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    SLOGE("Bad magic for real block device %s\n", fname);
5468f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    goto errout;
5478f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
5488f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
549c96a5f8edf65a8abe441d0cfd3ce227bdf1bf55fKenny Root  if (crypt_ftr->major_version != CURRENT_MAJOR_VERSION) {
550c96a5f8edf65a8abe441d0cfd3ce227bdf1bf55fKenny Root    SLOGE("Cannot understand major version %d real block device footer; expected %d\n",
551c96a5f8edf65a8abe441d0cfd3ce227bdf1bf55fKenny Root          crypt_ftr->major_version, CURRENT_MAJOR_VERSION);
5528f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    goto errout;
5538f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
5548f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
555c96a5f8edf65a8abe441d0cfd3ce227bdf1bf55fKenny Root  if (crypt_ftr->minor_version > CURRENT_MINOR_VERSION) {
556c96a5f8edf65a8abe441d0cfd3ce227bdf1bf55fKenny Root    SLOGW("Warning: crypto footer minor version %d, expected <= %d, continuing...\n",
557c96a5f8edf65a8abe441d0cfd3ce227bdf1bf55fKenny Root          crypt_ftr->minor_version, CURRENT_MINOR_VERSION);
5588f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
5598f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
560160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  /* If this is a verion 1.0 crypt_ftr, make it a 1.1 crypt footer, and update the
561160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall   * copy on disk before returning.
562160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall   */
563c96a5f8edf65a8abe441d0cfd3ce227bdf1bf55fKenny Root  if (crypt_ftr->minor_version < CURRENT_MINOR_VERSION) {
564160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    upgrade_crypt_ftr(fd, crypt_ftr, starting_off);
565e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall  }
566e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall
5678f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  /* Success! */
5688f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  rc = 0;
5698f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
5708f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrallerrout:
5718f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  close(fd);
5728f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  return rc;
5738f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
5748f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
575160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic int validate_persistent_data_storage(struct crypt_mnt_ftr *crypt_ftr)
576160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
577160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (crypt_ftr->persist_data_offset[0] + crypt_ftr->persist_data_size >
578160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        crypt_ftr->persist_data_offset[1]) {
579160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Crypt_ftr persist data regions overlap");
580160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
581160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
582160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
583160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (crypt_ftr->persist_data_offset[0] >= crypt_ftr->persist_data_offset[1]) {
584160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Crypt_ftr persist data region 0 starts after region 1");
585160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
586160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
587160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
588160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (((crypt_ftr->persist_data_offset[1] + crypt_ftr->persist_data_size) -
589160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        (crypt_ftr->persist_data_offset[0] - CRYPT_FOOTER_TO_PERSIST_OFFSET)) >
590160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        CRYPT_FOOTER_OFFSET) {
591160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Persistent data extends past crypto footer");
592160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
593160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
594160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
595160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return 0;
596160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
597160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
598160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic int load_persistent_data(void)
599160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
600160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    struct crypt_mnt_ftr crypt_ftr;
601160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    struct crypt_persist_data *pdata = NULL;
602160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    char encrypted_state[PROPERTY_VALUE_MAX];
603160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    char *fname;
604160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    int found = 0;
605160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    int fd;
606160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    int ret;
607160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    int i;
608160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
609160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (persist_data) {
610160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        /* Nothing to do, we've already loaded or initialized it */
611160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return 0;
612160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
613160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
614160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
615160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    /* If not encrypted, just allocate an empty table and initialize it */
616160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    property_get("ro.crypto.state", encrypted_state, "");
617160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (strcmp(encrypted_state, "encrypted") ) {
6184375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang        pdata = (crypt_persist_data*)malloc(CRYPT_PERSIST_DATA_SIZE);
619160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (pdata) {
620160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            init_empty_persist_data(pdata, CRYPT_PERSIST_DATA_SIZE);
621160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            persist_data = pdata;
622160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            return 0;
623160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
624160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
625160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
626160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
627160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if(get_crypt_ftr_and_key(&crypt_ftr)) {
628160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
629160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
630160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
6318561b5c9f5d2f9c5e3f8e2963bdffe9ff3706b04Paul Lawrence    if ((crypt_ftr.major_version < 1)
6328561b5c9f5d2f9c5e3f8e2963bdffe9ff3706b04Paul Lawrence        || (crypt_ftr.major_version == 1 && crypt_ftr.minor_version < 1)) {
633160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Crypt_ftr version doesn't support persistent data");
634160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
635160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
636160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
637160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (get_crypt_ftr_info(&fname, NULL)) {
638160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
639160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
640160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
641160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    ret = validate_persistent_data_storage(&crypt_ftr);
642160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (ret) {
643160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
644160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
645160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
646ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    fd = open(fname, O_RDONLY|O_CLOEXEC);
647160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (fd < 0) {
648160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Cannot open %s metadata file", fname);
649160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
650160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
651160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
6524375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    pdata = (crypt_persist_data*)malloc(crypt_ftr.persist_data_size);
653300dae7c38e6853148a998dfc1030b2be40490b5Paul Lawrence    if (pdata == NULL) {
654300dae7c38e6853148a998dfc1030b2be40490b5Paul Lawrence        SLOGE("Cannot allocate memory for persistent data");
655300dae7c38e6853148a998dfc1030b2be40490b5Paul Lawrence        goto err;
656160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
657160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
658160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    for (i = 0; i < 2; i++) {
659160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (lseek64(fd, crypt_ftr.persist_data_offset[i], SEEK_SET) < 0) {
660160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            SLOGE("Cannot seek to read persistent data on %s", fname);
661160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            goto err2;
662160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
663160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (unix_read(fd, pdata, crypt_ftr.persist_data_size) < 0){
664160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            SLOGE("Error reading persistent data on iteration %d", i);
665160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            goto err2;
666160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
667160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (pdata->persist_magic == PERSIST_DATA_MAGIC) {
668160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            found = 1;
669160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            break;
670160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
671160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
672160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
673160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (!found) {
674160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGI("Could not find valid persistent data, creating");
675160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        init_empty_persist_data(pdata, crypt_ftr.persist_data_size);
676160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
677160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
678160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    /* Success */
679160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    persist_data = pdata;
680160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    close(fd);
681160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return 0;
682160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
683160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallerr2:
684160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    free(pdata);
685160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
686160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallerr:
687160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    close(fd);
688160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
689160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
690160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
691160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallstatic int save_persistent_data(void)
692160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
693160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    struct crypt_mnt_ftr crypt_ftr;
694160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    struct crypt_persist_data *pdata;
695160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    char *fname;
696160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    off64_t write_offset;
697160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    off64_t erase_offset;
698160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    int fd;
699160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    int ret;
700160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
701160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (persist_data == NULL) {
702160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("No persistent data to save");
703160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
704160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
705160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
706160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if(get_crypt_ftr_and_key(&crypt_ftr)) {
707160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
708160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
709160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
7108561b5c9f5d2f9c5e3f8e2963bdffe9ff3706b04Paul Lawrence    if ((crypt_ftr.major_version < 1)
7118561b5c9f5d2f9c5e3f8e2963bdffe9ff3706b04Paul Lawrence        || (crypt_ftr.major_version == 1 && crypt_ftr.minor_version < 1)) {
712160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Crypt_ftr version doesn't support persistent data");
713160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
714160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
715160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
716160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    ret = validate_persistent_data_storage(&crypt_ftr);
717160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (ret) {
718160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
719160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
720160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
721160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (get_crypt_ftr_info(&fname, NULL)) {
722160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
723160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
724160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
725ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    fd = open(fname, O_RDWR|O_CLOEXEC);
726160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (fd < 0) {
727160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Cannot open %s metadata file", fname);
728160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
729160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
730160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
7314375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    pdata = (crypt_persist_data*)malloc(crypt_ftr.persist_data_size);
732160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (pdata == NULL) {
733160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Cannot allocate persistant data");
734160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        goto err;
735160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
736160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
737160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (lseek64(fd, crypt_ftr.persist_data_offset[0], SEEK_SET) < 0) {
738160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Cannot seek to read persistent data on %s", fname);
739160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        goto err2;
740160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
741160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
742160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (unix_read(fd, pdata, crypt_ftr.persist_data_size) < 0) {
743160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            SLOGE("Error reading persistent data before save");
744160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            goto err2;
745160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
746160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
747160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (pdata->persist_magic == PERSIST_DATA_MAGIC) {
748160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        /* The first copy is the curent valid copy, so write to
749160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall         * the second copy and erase this one */
750160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall       write_offset = crypt_ftr.persist_data_offset[1];
751160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall       erase_offset = crypt_ftr.persist_data_offset[0];
752160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    } else {
753160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        /* The second copy must be the valid copy, so write to
754160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall         * the first copy, and erase the second */
755160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall       write_offset = crypt_ftr.persist_data_offset[0];
756160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall       erase_offset = crypt_ftr.persist_data_offset[1];
757160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
758160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
759160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    /* Write the new copy first, if successful, then erase the old copy */
76096dbee7bd6c64c0d38b4e390e12851e02b674b87Björn Landström    if (lseek64(fd, write_offset, SEEK_SET) < 0) {
761160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Cannot seek to write persistent data");
762160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        goto err2;
763160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
764160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (unix_write(fd, persist_data, crypt_ftr.persist_data_size) ==
765160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        (int) crypt_ftr.persist_data_size) {
76696dbee7bd6c64c0d38b4e390e12851e02b674b87Björn Landström        if (lseek64(fd, erase_offset, SEEK_SET) < 0) {
767160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            SLOGE("Cannot seek to erase previous persistent data");
768160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            goto err2;
769160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
770160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        fsync(fd);
771160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        memset(pdata, 0, crypt_ftr.persist_data_size);
772160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (unix_write(fd, pdata, crypt_ftr.persist_data_size) !=
773160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            (int) crypt_ftr.persist_data_size) {
774160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            SLOGE("Cannot write to erase previous persistent data");
775160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            goto err2;
776160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
777160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        fsync(fd);
778160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    } else {
779160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        SLOGE("Cannot write to save persistent data");
780160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        goto err2;
781160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
782160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
783160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    /* Success */
784160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    free(pdata);
785160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    close(fd);
786160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return 0;
787160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
788160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallerr2:
789160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    free(pdata);
790160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallerr:
791160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    close(fd);
792160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
793160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
794160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
7958f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall/* Convert a binary key of specified length into an ascii hex string equivalent,
7968f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * without the leading 0x and with null termination
7978f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall */
7989c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeystatic void convert_key_to_hex_ascii(const unsigned char *master_key,
7993bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence                                     unsigned int keysize, char *master_key_ascii) {
8003bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence    unsigned int i, a;
8013bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence    unsigned char nibble;
8028f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
8033bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence    for (i=0, a=0; i<keysize; i++, a+=2) {
8043bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence        /* For each byte, write out two ascii hex digits */
8053bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence        nibble = (master_key[i] >> 4) & 0xf;
8063bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence        master_key_ascii[a] = nibble + (nibble > 9 ? 0x37 : 0x30);
8078f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
8083bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence        nibble = master_key[i] & 0xf;
8093bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence        master_key_ascii[a+1] = nibble + (nibble > 9 ? 0x37 : 0x30);
8103bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence    }
8118f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
8123bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence    /* Add the null termination */
8133bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence    master_key_ascii[a] = '\0';
8148f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
8158f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
8168f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
8179c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeystatic int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr,
8189c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        const unsigned char *master_key, const char *real_blk_name,
8199c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        const char *name, int fd, const char *extra_params) {
8204375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang  alignas(struct dm_ioctl) char buffer[DM_CRYPT_BUF_SIZE];
821db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  struct dm_ioctl *io;
822db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  struct dm_target_spec *tgt;
823db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  char *crypt_params;
824db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  char master_key_ascii[129]; /* Large enough to hold 512 bit key and null */
825605d7ae18d6e33b5dc1f6bb813ae32781498a4cdGeorge Burgess IV  size_t buff_offset;
826db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  int i;
827db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
828db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  io = (struct dm_ioctl *) buffer;
829db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
830db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  /* Load the mapping table for this device */
831db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
832db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
833db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
834db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  io->target_count = 1;
835db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  tgt->status = 0;
836db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  tgt->sector_start = 0;
837db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  tgt->length = crypt_ftr->fs_size;
83887701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani  strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME);
839db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
840db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
841db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
842605d7ae18d6e33b5dc1f6bb813ae32781498a4cdGeorge Burgess IV
843605d7ae18d6e33b5dc1f6bb813ae32781498a4cdGeorge Burgess IV  buff_offset = crypt_params - buffer;
844605d7ae18d6e33b5dc1f6bb813ae32781498a4cdGeorge Burgess IV  snprintf(crypt_params, sizeof(buffer) - buff_offset, "%s %s 0 %s 0 %s",
845605d7ae18d6e33b5dc1f6bb813ae32781498a4cdGeorge Burgess IV           crypt_ftr->crypto_type_name, master_key_ascii, real_blk_name,
846605d7ae18d6e33b5dc1f6bb813ae32781498a4cdGeorge Burgess IV           extra_params);
847db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  crypt_params += strlen(crypt_params) + 1;
848db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  crypt_params = (char *) (((unsigned long)crypt_params + 7) & ~8); /* Align to an 8 byte boundary */
849db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  tgt->next = crypt_params - buffer;
850db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
851db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  for (i = 0; i < TABLE_LOAD_RETRIES; i++) {
852db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    if (! ioctl(fd, DM_TABLE_LOAD, io)) {
853db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall      break;
854db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    }
855db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    usleep(500000);
856db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  }
857db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
858db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  if (i == TABLE_LOAD_RETRIES) {
859db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    /* We failed to load the table, return an error */
860db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    return -1;
861db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  } else {
862db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    return i + 1;
863db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  }
864db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall}
865db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
866db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
867db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrallstatic int get_dm_crypt_version(int fd, const char *name,  int *version)
868db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall{
869db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    char buffer[DM_CRYPT_BUF_SIZE];
870db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    struct dm_ioctl *io;
871db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    struct dm_target_versions *v;
872db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
873db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    io = (struct dm_ioctl *) buffer;
874db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
875db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
876db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
877db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    if (ioctl(fd, DM_LIST_VERSIONS, io)) {
878db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall        return -1;
879db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    }
880db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
881db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    /* Iterate over the returned versions, looking for name of "crypt".
882db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall     * When found, get and return the version.
883db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall     */
884db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    v = (struct dm_target_versions *) &buffer[sizeof(struct dm_ioctl)];
885db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    while (v->next) {
886db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall        if (! strcmp(v->name, "crypt")) {
887db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall            /* We found the crypt driver, return the version, and get out */
888db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall            version[0] = v->version[0];
889db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall            version[1] = v->version[1];
890db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall            version[2] = v->version[2];
891db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall            return 0;
892db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall        }
893db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall        v = (struct dm_target_versions *)(((char *)v) + v->next);
894db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    }
895db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
896db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall    return -1;
897db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall}
898db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall
8999c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeystatic int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr,
9009c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        const unsigned char *master_key, const char *real_blk_name,
9019c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        char *crypto_blk_name, const char *name) {
9028f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  char buffer[DM_CRYPT_BUF_SIZE];
9038f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  struct dm_ioctl *io;
9048f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  unsigned int minor;
90587701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani  int fd=0;
90625a5213c1f37dfdd15d0c52785addab15a8536b3Daniel Rosenberg  int err;
9078f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  int retval = -1;
908db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  int version[3];
9094375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang  const char *extra_params;
910db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  int load_count;
9118f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
912ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey  if ((fd = open("/dev/device-mapper", O_RDWR|O_CLOEXEC)) < 0 ) {
9138f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    SLOGE("Cannot open device-mapper\n");
9148f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    goto errout;
9158f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
9168f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9178f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  io = (struct dm_ioctl *) buffer;
9188f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9198f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
92025a5213c1f37dfdd15d0c52785addab15a8536b3Daniel Rosenberg  err = ioctl(fd, DM_DEV_CREATE, io);
92125a5213c1f37dfdd15d0c52785addab15a8536b3Daniel Rosenberg  if (err) {
92225a5213c1f37dfdd15d0c52785addab15a8536b3Daniel Rosenberg    SLOGE("Cannot create dm-crypt device %s: %s\n", name, strerror(errno));
9238f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    goto errout;
9248f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
9258f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9268f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  /* Get the device status, in particular, the name of it's device file */
9278f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
9288f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  if (ioctl(fd, DM_DEV_STATUS, io)) {
9298f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    SLOGE("Cannot retrieve dm-crypt device status\n");
9308f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    goto errout;
9318f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
9328f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
9338f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  snprintf(crypto_blk_name, MAXPATHLEN, "/dev/block/dm-%u", minor);
9348f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
935db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  extra_params = "";
936db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  if (! get_dm_crypt_version(fd, name, version)) {
937db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall      /* Support for allow_discards was added in version 1.11.0 */
938db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall      if ((version[0] >= 2) ||
939db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall          ((version[0] == 1) && (version[1] >= 11))) {
940db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall          extra_params = "1 allow_discards";
941db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall          SLOGI("Enabling support for allow_discards in dmcrypt.\n");
942db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall      }
943e919efea94b178ed214ed2e78ef0d008727d62abKen Sumrall  }
944e919efea94b178ed214ed2e78ef0d008727d62abKen Sumrall
945db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name,
946db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall                                         fd, extra_params);
947db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  if (load_count < 0) {
9488f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall      SLOGE("Cannot load dm-crypt mapping table.\n");
9498f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall      goto errout;
950db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  } else if (load_count > 1) {
951db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall      SLOGI("Took %d tries to load dmcrypt table.\n", load_count);
9528f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
9538f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9548f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  /* Resume this device to activate it */
955db5e026058927347ccff8f170c8f160b28cbc75bKen Sumrall  ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
9568f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9578f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  if (ioctl(fd, DM_DEV_SUSPEND, io)) {
9588f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    SLOGE("Cannot resume the dm-crypt device\n");
9598f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    goto errout;
9608f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
9618f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9628f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  /* We made it here with no errors.  Woot! */
9638f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  retval = 0;
9648f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9658f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrallerrout:
9668f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  close(fd);   /* If fd is <0 from a failed open call, it's safe to just ignore the close error */
9678f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9688f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  return retval;
9698f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
9708f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9714375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wangstatic int delete_crypto_blk_dev(const char *name)
9728f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
9738f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  int fd;
9748f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  char buffer[DM_CRYPT_BUF_SIZE];
9758f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  struct dm_ioctl *io;
9768f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  int retval = -1;
9778f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
978ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey  if ((fd = open("/dev/device-mapper", O_RDWR|O_CLOEXEC)) < 0 ) {
9798f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    SLOGE("Cannot open device-mapper\n");
9808f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    goto errout;
9818f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
9828f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9838f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  io = (struct dm_ioctl *) buffer;
9848f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9858f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
9868f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  if (ioctl(fd, DM_DEV_REMOVE, io)) {
9878f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    SLOGE("Cannot remove dm-crypt device\n");
9888f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    goto errout;
9898f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
9908f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9918f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  /* We made it here with no errors.  Woot! */
9928f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  retval = 0;
9938f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9948f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrallerrout:
9958f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  close(fd);    /* If fd is <0 from a failed open call, it's safe to just ignore the close error */
9968f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9978f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  return retval;
9988f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
9998f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
10008f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
100169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrencestatic int pbkdf2(const char *passwd, const unsigned char *salt,
1002f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                  unsigned char *ikey, void *params UNUSED)
1003f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence{
100469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    SLOGI("Using pbkdf2 for cryptfs KDF");
100569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
10068f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    /* Turn the password into a key and IV that can decrypt the master key */
1007bf0d972ab4aa04918dc57ba277454ea65bbdee26Adam Langley    return PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), salt, SALT_LEN,
1008bf0d972ab4aa04918dc57ba277454ea65bbdee26Adam Langley                                  HASH_COUNT, KEY_LEN_BYTES + IV_LEN_BYTES,
1009bf0d972ab4aa04918dc57ba277454ea65bbdee26Adam Langley                                  ikey) != 1;
10108ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall}
10118ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
101269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrencestatic int scrypt(const char *passwd, const unsigned char *salt,
1013f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                  unsigned char *ikey, void *params)
1014f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence{
101569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    SLOGI("Using scrypt for cryptfs KDF");
101669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
1017c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    struct crypt_mnt_ftr *ftr = (struct crypt_mnt_ftr *) params;
1018c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
1019c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    int N = 1 << ftr->N_factor;
1020c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    int r = 1 << ftr->r_factor;
1021c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    int p = 1 << ftr->p_factor;
1022c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
1023c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    /* Turn the password into a key and IV that can decrypt the master key */
1024f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    unsigned int keysize;
10253bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence    crypto_scrypt((const uint8_t*)passwd, strlen(passwd),
10263bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence                  salt, SALT_LEN, N, r, p, ikey,
10273bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence                  KEY_LEN_BYTES + IV_LEN_BYTES);
1028f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
10293bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence   return 0;
1030c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root}
1031c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
103269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrencestatic int scrypt_keymaster(const char *passwd, const unsigned char *salt,
103369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence                            unsigned char *ikey, void *params)
103469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence{
103569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    SLOGI("Using scrypt with keymaster for cryptfs KDF");
103669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
103769f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    int rc;
103869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    size_t signature_size;
103969f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    unsigned char* signature;
104069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    struct crypt_mnt_ftr *ftr = (struct crypt_mnt_ftr *) params;
104169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
104269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    int N = 1 << ftr->N_factor;
104369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    int r = 1 << ftr->r_factor;
104469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    int p = 1 << ftr->p_factor;
104569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
10463bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence    rc = crypto_scrypt((const uint8_t*)passwd, strlen(passwd),
10473bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence                       salt, SALT_LEN, N, r, p, ikey,
10483bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence                       KEY_LEN_BYTES + IV_LEN_BYTES);
104969f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
105069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    if (rc) {
105169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        SLOGE("scrypt failed");
105269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        return -1;
105369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    }
105469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
1055e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden    if (keymaster_sign_object(ftr, ikey, KEY_LEN_BYTES + IV_LEN_BYTES,
1056e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden                              &signature, &signature_size)) {
1057e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden        SLOGE("Signing failed");
1058e17a9c4ad3ebb4051853a4860b18973e1a01ce11Shawn Willden        return -1;
105969f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    }
106069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
106169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    rc = crypto_scrypt(signature, signature_size, salt, SALT_LEN,
106269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence                       N, r, p, ikey, KEY_LEN_BYTES + IV_LEN_BYTES);
106369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    free(signature);
106469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
106569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    if (rc) {
106669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        SLOGE("scrypt failed");
106769f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        return -1;
106869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    }
106969f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
107069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    return 0;
107169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence}
107269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
107369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrencestatic int encrypt_master_key(const char *passwd, const unsigned char *salt,
107469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence                              const unsigned char *decrypted_master_key,
1075c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root                              unsigned char *encrypted_master_key,
1076c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root                              struct crypt_mnt_ftr *crypt_ftr)
10778ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall{
10788ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    unsigned char ikey[32+32] = { 0 }; /* Big enough to hold a 256 bit key and 256 bit IV */
10798ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    EVP_CIPHER_CTX e_ctx;
10808ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    int encrypted_len, final_len;
1081d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    int rc = 0;
10828ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
1083d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    /* Turn the password into an intermediate key and IV that can decrypt the master key */
1084c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    get_device_scrypt_params(crypt_ftr);
108569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
108669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    switch (crypt_ftr->kdf_type) {
108769f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    case KDF_SCRYPT_KEYMASTER:
108869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        if (keymaster_create_key(crypt_ftr)) {
108969f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence            SLOGE("keymaster_create_key failed");
109069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence            return -1;
109169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        }
109269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
109369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        if (scrypt_keymaster(passwd, salt, ikey, crypt_ftr)) {
109469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence            SLOGE("scrypt failed");
109569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence            return -1;
109669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        }
109769f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        break;
109869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
109969f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    case KDF_SCRYPT:
110069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        if (scrypt(passwd, salt, ikey, crypt_ftr)) {
110169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence            SLOGE("scrypt failed");
110269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence            return -1;
110369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        }
110469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        break;
110569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
110669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    default:
110769f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        SLOGE("Invalid kdf_type");
1108f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        return -1;
1109f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    }
1110c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
11118f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    /* Initialize the decryption engine */
1112889c4f1e36f69c1d5a9a92a6ba40d8a729d3f7b0Adam Langley    EVP_CIPHER_CTX_init(&e_ctx);
1113889c4f1e36f69c1d5a9a92a6ba40d8a729d3f7b0Adam Langley    if (! EVP_EncryptInit_ex(&e_ctx, EVP_aes_128_cbc(), NULL, ikey, ikey+KEY_LEN_BYTES)) {
11148f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        SLOGE("EVP_EncryptInit failed\n");
11158f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        return -1;
11168f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
11178f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    EVP_CIPHER_CTX_set_padding(&e_ctx, 0); /* Turn off padding as our data is block aligned */
11188ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
11198f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    /* Encrypt the master key */
11208ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    if (! EVP_EncryptUpdate(&e_ctx, encrypted_master_key, &encrypted_len,
1121731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                            decrypted_master_key, KEY_LEN_BYTES)) {
11228f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        SLOGE("EVP_EncryptUpdate failed\n");
11238f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        return -1;
11248f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
1125889c4f1e36f69c1d5a9a92a6ba40d8a729d3f7b0Adam Langley    if (! EVP_EncryptFinal_ex(&e_ctx, encrypted_master_key + encrypted_len, &final_len)) {
11268f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        SLOGE("EVP_EncryptFinal failed\n");
11278f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        return -1;
11288f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
11298f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
11308f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    if (encrypted_len + final_len != KEY_LEN_BYTES) {
11318f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        SLOGE("EVP_Encryption length check failed with %d, %d bytes\n", encrypted_len, final_len);
11328f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        return -1;
11338f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
113469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
1135d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    /* Store the scrypt of the intermediate key, so we can validate if it's a
1136d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence       password error or mount error when things go wrong.
1137d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence       Note there's no need to check for errors, since if this is incorrect, we
1138d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence       simply won't wipe userdata, which is the correct default behavior
1139d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    */
1140d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    int N = 1 << crypt_ftr->N_factor;
1141d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    int r = 1 << crypt_ftr->r_factor;
1142d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    int p = 1 << crypt_ftr->p_factor;
1143d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence
1144d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    rc = crypto_scrypt(ikey, KEY_LEN_BYTES,
1145d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                       crypt_ftr->salt, sizeof(crypt_ftr->salt), N, r, p,
1146d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                       crypt_ftr->scrypted_intermediate_key,
1147d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                       sizeof(crypt_ftr->scrypted_intermediate_key));
1148d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence
1149d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    if (rc) {
1150d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence      SLOGE("encrypt_master_key: crypto_scrypt failed");
1151d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    }
1152d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence
115306dc31181752c3e59b4c5b58b24f023640898564Thurston Hou Yeen Dang    EVP_CIPHER_CTX_cleanup(&e_ctx);
115406dc31181752c3e59b4c5b58b24f023640898564Thurston Hou Yeen Dang
115569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    return 0;
11568f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
11578f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1158731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic int decrypt_master_key_aux(const char *passwd, unsigned char *salt,
1159d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                                  unsigned char *encrypted_master_key,
1160d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                                  unsigned char *decrypted_master_key,
1161d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                                  kdf_func kdf, void *kdf_params,
1162d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                                  unsigned char** intermediate_key,
1163d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                                  size_t* intermediate_key_size)
11648f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
11658f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  unsigned char ikey[32+32] = { 0 }; /* Big enough to hold a 256 bit key and 256 bit IV */
11668f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  EVP_CIPHER_CTX d_ctx;
11678f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  int decrypted_len, final_len;
11688f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1169d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence  /* Turn the password into an intermediate key and IV that can decrypt the
1170d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence     master key */
1171f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence  if (kdf(passwd, salt, ikey, kdf_params)) {
1172f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    SLOGE("kdf failed");
1173f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    return -1;
1174f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence  }
11758f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
11768f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  /* Initialize the decryption engine */
1177889c4f1e36f69c1d5a9a92a6ba40d8a729d3f7b0Adam Langley  EVP_CIPHER_CTX_init(&d_ctx);
1178889c4f1e36f69c1d5a9a92a6ba40d8a729d3f7b0Adam Langley  if (! EVP_DecryptInit_ex(&d_ctx, EVP_aes_128_cbc(), NULL, ikey, ikey+KEY_LEN_BYTES)) {
11798f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return -1;
11808f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
11818f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  EVP_CIPHER_CTX_set_padding(&d_ctx, 0); /* Turn off padding as our data is block aligned */
11828f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  /* Decrypt the master key */
11838f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  if (! EVP_DecryptUpdate(&d_ctx, decrypted_master_key, &decrypted_len,
11848f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall                            encrypted_master_key, KEY_LEN_BYTES)) {
11858f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return -1;
11868f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
1187889c4f1e36f69c1d5a9a92a6ba40d8a729d3f7b0Adam Langley  if (! EVP_DecryptFinal_ex(&d_ctx, decrypted_master_key + decrypted_len, &final_len)) {
11888f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return -1;
11898f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
11908f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
11918f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  if (decrypted_len + final_len != KEY_LEN_BYTES) {
11928f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return -1;
11938f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
1194d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence
1195d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence  /* Copy intermediate key if needed by params */
1196d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence  if (intermediate_key && intermediate_key_size) {
1197d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    *intermediate_key = (unsigned char*) malloc(KEY_LEN_BYTES);
1198e8167afe55d4e33e93d7270701403708d9a03e7eGreg Kaiser    if (*intermediate_key) {
1199d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence      memcpy(*intermediate_key, ikey, KEY_LEN_BYTES);
1200d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence      *intermediate_key_size = KEY_LEN_BYTES;
1201d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    }
1202d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence  }
1203d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence
120406dc31181752c3e59b4c5b58b24f023640898564Thurston Hou Yeen Dang  EVP_CIPHER_CTX_cleanup(&d_ctx);
120506dc31181752c3e59b4c5b58b24f023640898564Thurston Hou Yeen Dang
1206d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence  return 0;
12078f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
12088f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1209c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Rootstatic void get_kdf_func(struct crypt_mnt_ftr *ftr, kdf_func *kdf, void** kdf_params)
12108ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall{
1211db3730c454ef706dffee9bde0f9bf54e95ab06f8Paul Lawrence    if (ftr->kdf_type == KDF_SCRYPT_KEYMASTER) {
121269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        *kdf = scrypt_keymaster;
121369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        *kdf_params = ftr;
121469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    } else if (ftr->kdf_type == KDF_SCRYPT) {
1215c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        *kdf = scrypt;
1216c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        *kdf_params = ftr;
1217c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    } else {
1218c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        *kdf = pbkdf2;
1219c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        *kdf_params = NULL;
1220c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    }
1221c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root}
1222c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
1223731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic int decrypt_master_key(const char *passwd, unsigned char *decrypted_master_key,
1224d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                              struct crypt_mnt_ftr *crypt_ftr,
1225d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                              unsigned char** intermediate_key,
1226d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                              size_t* intermediate_key_size)
1227c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root{
1228c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    kdf_func kdf;
1229c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    void *kdf_params;
1230c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    int ret;
1231c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
1232c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    get_kdf_func(crypt_ftr, &kdf, &kdf_params);
1233d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    ret = decrypt_master_key_aux(passwd, crypt_ftr->salt, crypt_ftr->master_key,
1234d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                                 decrypted_master_key, kdf, kdf_params,
1235d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                                 intermediate_key, intermediate_key_size);
1236c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    if (ret != 0) {
1237c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        SLOGW("failure decrypting master key");
1238c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    }
1239c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
1240c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    return ret;
1241c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root}
1242c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
12434375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wangstatic int create_encrypted_random_key(const char *passwd, unsigned char *master_key, unsigned char *salt,
1244c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root        struct crypt_mnt_ftr *crypt_ftr) {
12458ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    int fd;
1246e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall    unsigned char key_buf[KEY_LEN_BYTES];
12478ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
12488ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    /* Get some random bits for a key */
1249ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC);
1250e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall    read(fd, key_buf, sizeof(key_buf));
1251e87440703663f5ee326326f6438f3b00ea315623Ken Sumrall    read(fd, salt, SALT_LEN);
12528ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    close(fd);
12538ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
12548ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    /* Now encrypt it with the password */
1255c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr);
12568ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall}
12578ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
12582f32cda63bf5c86db880d36029a27c8597fb5e3cPaul Lawrenceint wait_and_unmount(const char *mountpoint, bool kill)
12598f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
1260955653ebff68e29f5aeab3f05fddc199474e4174Greg Hackmann    int i, err, rc;
12612eaf7138528d30c331d83ab8346a97e66b5499e2Ken Sumrall#define WAIT_UNMOUNT_COUNT 20
12628f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
12638f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    /*  Now umount the tmpfs filesystem */
12648f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    for (i=0; i<WAIT_UNMOUNT_COUNT; i++) {
12656e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann        if (umount(mountpoint) == 0) {
12666e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann            break;
12676e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann        }
12686e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann
12696e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann        if (errno == EINVAL) {
12706e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann            /* EINVAL is returned if the directory is not a mountpoint,
12716e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann             * i.e. there is no filesystem mounted there.  So just get out.
12726e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann             */
12736e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann            break;
12746e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann        }
12756e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann
12766e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann        err = errno;
12776e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann
12786e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann        /* If allowed, be increasingly aggressive before the last two retries */
12796e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann        if (kill) {
12806e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann            if (i == (WAIT_UNMOUNT_COUNT - 3)) {
12816e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann                SLOGW("sending SIGHUP to processes with open files\n");
128236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                vold_killProcessesWithOpenFiles(mountpoint, SIGTERM);
12836e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann            } else if (i == (WAIT_UNMOUNT_COUNT - 2)) {
12846e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann                SLOGW("sending SIGKILL to processes with open files\n");
128536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                vold_killProcessesWithOpenFiles(mountpoint, SIGKILL);
128629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            }
12878f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        }
12886e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann
12896e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann        sleep(1);
12908f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
12918f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
12928f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    if (i < WAIT_UNMOUNT_COUNT) {
12938f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall      SLOGD("unmounting %s succeeded\n", mountpoint);
12948f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall      rc = 0;
12958f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    } else {
12963f14fe45a3e7bc0d12ba26d20a36d355a10f623ejessica_yu      vold_killProcessesWithOpenFiles(mountpoint, 0);
1297955653ebff68e29f5aeab3f05fddc199474e4174Greg Hackmann      SLOGE("unmounting %s failed: %s\n", mountpoint, strerror(err));
12988f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall      rc = -1;
12998f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
13008f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
13018f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return rc;
13028f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
13038f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
13048ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrallstatic int prep_data_fs(void)
13058ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall{
13068ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    int i;
13078ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
130847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    // NOTE: post_fs_data results in init calling back around to vold, so all
130947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    // callers to this method must be async
131047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
13118ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    /* Do the prep of the /data filesystem */
13128ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    property_set("vold.post_fs_data_done", "0");
13138ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    property_set("vold.decrypt", "trigger_post_fs_data");
13148ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    SLOGD("Just triggered post_fs_data\n");
13158ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
1316c587269c5a34d4e7412ff42e53ed6312359a8505Ken Sumrall    /* Wait a max of 50 seconds, hopefully it takes much less */
13174375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    if (!android::base::WaitForProperty("vold.post_fs_data_done",
13184375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang                                        "1",
13194375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang                                        std::chrono::seconds(50))) {
13208ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        /* Ugh, we failed to prep /data in time.  Bail. */
1321c587269c5a34d4e7412ff42e53ed6312359a8505Ken Sumrall        SLOGE("post_fs_data timed out!\n");
13228ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        return -1;
13238ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    } else {
13248ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        SLOGD("post_fs_data done\n");
13258ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        return 0;
13268ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    }
13278ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall}
13288ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
132974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrencestatic void cryptfs_set_corrupt()
133074f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence{
133174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    // Mark the footer as bad
133274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    struct crypt_mnt_ftr crypt_ftr;
133374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    if (get_crypt_ftr_and_key(&crypt_ftr)) {
133474f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        SLOGE("Failed to get crypto footer - panic");
133574f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        return;
133674f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    }
133774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
133874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    crypt_ftr.flags |= CRYPT_DATA_CORRUPT;
133974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    if (put_crypt_ftr_and_key(&crypt_ftr)) {
134074f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        SLOGE("Failed to set crypto footer - panic");
134174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        return;
134274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    }
134374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence}
134474f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
134574f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrencestatic void cryptfs_trigger_restart_min_framework()
134674f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence{
134774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    if (fs_mgr_do_tmpfs_mount(DATA_MNT_POINT)) {
134874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      SLOGE("Failed to mount tmpfs on data - panic");
134974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      return;
135074f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    }
135174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
135274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    if (property_set("vold.decrypt", "trigger_post_fs_data")) {
135374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        SLOGE("Failed to trigger post fs data - panic");
135474f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        return;
135574f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    }
135674f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
135774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    if (property_set("vold.decrypt", "trigger_restart_min_framework")) {
135874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        SLOGE("Failed to trigger restart min framework - panic");
135974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        return;
136074f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    }
136174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence}
136274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
13638e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence/* returns < 0 on failure */
1364f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrencestatic int cryptfs_restart_internal(int restart_main)
13658f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
13666864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall    char crypto_blkdev[MAXPATHLEN];
13678439dc9fd569794b1a31f67cf43d9212de33eeccTim Murray    int rc = -1;
13680cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall    static int restart_successful = 0;
13690cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall
13700cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall    /* Validate that it's OK to call this routine */
137170a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks    if (! master_key_saved) {
13720cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall        SLOGE("Encrypted filesystem not validated, aborting");
13730cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall        return -1;
13740cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall    }
13750cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall
13760cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall    if (restart_successful) {
13770cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall        SLOGE("System already restarted with encrypted disk, aborting");
13780cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall        return -1;
13790cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall    }
13808f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1381f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    if (restart_main) {
1382f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        /* Here is where we shut down the framework.  The init scripts
1383f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * start all services in one of three classes: core, main or late_start.
1384f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * On boot, we start core and main.  Now, we stop main, but not core,
1385f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * as core includes vold and a few other really important things that
1386f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * we need to keep running.  Once main has stopped, we should be able
1387f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * to umount the tmpfs /data, then mount the encrypted /data.
1388f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * We then restart the class main, and also the class late_start.
1389f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * At the moment, I've only put a few things in late_start that I know
1390f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * are not needed to bring up the framework, and that also cause problems
1391f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * with unmounting the tmpfs /data, but I hope to add add more services
1392f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * to the late_start class as we optimize this to decrease the delay
1393f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * till the user is asked for the password to the filesystem.
1394f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         */
13958f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1396f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        /* The init files are setup to stop the class main when vold.decrypt is
1397f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * set to trigger_reset_main.
1398f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         */
1399f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        property_set("vold.decrypt", "trigger_reset_main");
1400f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGD("Just asked init to shut down class main\n");
14018f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1402f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        /* Ugh, shutting down the framework is not synchronous, so until it
1403f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * can be fixed, this horrible hack will wait a moment for it all to
1404f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * shut down before proceeding.  Without it, some devices cannot
1405f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         * restart the graphics services.
1406f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence         */
1407f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        sleep(2);
1408f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    }
14099dedfd473dc59e0277004e5b917e4eced02c8af5Ken Sumrall
14108f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    /* Now that the framework is shutdown, we should be able to umount()
14118f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall     * the tmpfs filesystem, and mount the real one.
14128f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall     */
14138f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
14146864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall    property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "");
14156864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall    if (strlen(crypto_blkdev) == 0) {
14166864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall        SLOGE("fs_crypto_blkdev not set\n");
14176864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall        return -1;
14186864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall    }
14196864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall
14206e8440fd5072a673dd861ffb531fc17b4673ad90Greg Hackmann    if (! (rc = wait_and_unmount(DATA_MNT_POINT, true)) ) {
14216fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker        /* If ro.crypto.readonly is set to 1, mount the decrypted
14226fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker         * filesystem readonly.  This is used when /data is mounted by
14236fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker         * recovery mode.
14246fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker         */
14256fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker        char ro_prop[PROPERTY_VALUE_MAX];
14266fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker        property_get("ro.crypto.readonly", ro_prop, "");
14276fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker        if (strlen(ro_prop) > 0 && atoi(ro_prop)) {
14286fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker            struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, DATA_MNT_POINT);
14296fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker            rec->flags |= MS_RDONLY;
14306fd5771337fddc13bfd8b8030a0767a9f0c47f98Doug Zongker        }
143162c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall
1432e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        /* If that succeeded, then mount the decrypted filesystem */
14338e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence        int retries = RETRY_MOUNT_ATTEMPTS;
14348e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence        int mount_rc;
1435df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep
1436df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep        /*
1437df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep         * fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
1438df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep         * partitions in the fsck domain.
1439df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep         */
1440df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep        if (setexeccon(secontextFsck())){
1441df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep            SLOGE("Failed to setexeccon");
1442df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep            return -1;
1443df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep        }
14448e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence        while ((mount_rc = fs_mgr_do_mount(fstab, DATA_MNT_POINT,
14458e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                                           crypto_blkdev, 0))
14468e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence               != 0) {
14478e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence            if (mount_rc == FS_MGR_DOMNT_BUSY) {
14488e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                /* TODO: invoke something similar to
14498e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                   Process::killProcessWithOpenFiles(DATA_MNT_POINT,
14508e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                                   retries > RETRY_MOUNT_ATTEMPT/2 ? 1 : 2 ) */
14518e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                SLOGI("Failed to mount %s because it is busy - waiting",
14528e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                      crypto_blkdev);
14538e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                if (--retries) {
14548e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                    sleep(RETRY_MOUNT_DELAY_SECONDS);
14558e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                } else {
14568e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                    /* Let's hope that a reboot clears away whatever is keeping
14578e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                       the mount busy */
14588e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                    cryptfs_reboot(reboot);
14598e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                }
14608e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence            } else {
14618e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                SLOGE("Failed to mount decrypted data");
14628e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                cryptfs_set_corrupt();
14638e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                cryptfs_trigger_restart_min_framework();
14648e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                SLOGI("Started framework to offer wipe");
1465df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep                if (setexeccon(NULL)) {
1466df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep                    SLOGE("Failed to setexeccon");
1467df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep                }
14688e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence                return -1;
14698e3f4510a88871a2d489ca4cdf7b738d4229053dPaul Lawrence            }
147074f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        }
1471df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep        if (setexeccon(NULL)) {
1472df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep            SLOGE("Failed to setexeccon");
1473df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep            return -1;
1474df725758628a0a250c82a9071af6a06a89e474fdJeff Vander Stoep        }
14758ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
1476e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        /* Create necessary paths on /data */
1477e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        if (prep_data_fs()) {
1478e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall            return -1;
1479e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        }
1480e2ef0c0da454a5b9224d340260e9ad5be46092feSeigo Nonaka        property_set("vold.decrypt", "trigger_load_persist_props");
14818f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1482e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        /* startup service classes main and late_start */
1483e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        property_set("vold.decrypt", "trigger_restart_framework");
1484e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        SLOGD("Just triggered restart_framework\n");
14858f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1486e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        /* Give it a few moments to get started */
1487e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        sleep(1);
14888f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
14898f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
14900cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall    if (rc == 0) {
14910cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall        restart_successful = 1;
14920cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall    }
14930cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall
14948f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return rc;
14958f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
14968f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1497f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrenceint cryptfs_restart(void)
1498f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence{
149905335c344d73411439774dfa548c633020e158e1Paul Lawrence    SLOGI("cryptfs_restart");
150038132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (e4crypt_is_native()) {
15017b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        SLOGE("cryptfs_restart not valid for file encryption:");
15027b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        return -1;
150305335c344d73411439774dfa548c633020e158e1Paul Lawrence    }
150405335c344d73411439774dfa548c633020e158e1Paul Lawrence
1505f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    /* Call internal implementation forcing a restart of main service group */
1506f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    return cryptfs_restart_internal(1);
1507f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence}
1508f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
15094375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wangstatic int do_crypto_complete(const char *mount_point)
15107f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall{
15117f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall  struct crypt_mnt_ftr crypt_ftr;
151229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall  char encrypted_state[PROPERTY_VALUE_MAX];
1513e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall  char key_loc[PROPERTY_VALUE_MAX];
15147f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall
15157f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall  property_get("ro.crypto.state", encrypted_state, "");
15167f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall  if (strcmp(encrypted_state, "encrypted") ) {
15177f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall    SLOGE("not running with encryption, aborting");
151874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    return CRYPTO_COMPLETE_NOT_ENCRYPTED;
15197f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall  }
15207f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall
15217b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence  // crypto_complete is full disk encrypted status
152238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley  if (e4crypt_is_native()) {
15237b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence    return CRYPTO_COMPLETE_NOT_ENCRYPTED;
152405335c344d73411439774dfa548c633020e158e1Paul Lawrence  }
152505335c344d73411439774dfa548c633020e158e1Paul Lawrence
1526160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  if (get_crypt_ftr_and_key(&crypt_ftr)) {
152756ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    fs_mgr_get_crypt_info(fstab, key_loc, 0, sizeof(key_loc));
1528e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall
1529e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall    /*
1530e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall     * Only report this error if key_loc is a file and it exists.
1531e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall     * If the device was never encrypted, and /data is not mountable for
1532e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall     * some reason, returning 1 should prevent the UI from presenting the
1533e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall     * a "enter password" screen, or worse, a "press button to wipe the
1534e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall     * device" screen.
1535e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall     */
1536e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall    if ((key_loc[0] == '/') && (access("key_loc", F_OK) == -1)) {
1537e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall      SLOGE("master key file does not exist, aborting");
153874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      return CRYPTO_COMPLETE_NOT_ENCRYPTED;
1539e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall    } else {
1540e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall      SLOGE("Error getting crypt footer and key\n");
154174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      return CRYPTO_COMPLETE_BAD_METADATA;
1542e1a458578474954ea38456aacedbaf2ddfd37988Ken Sumrall    }
15437f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall  }
15447f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall
154574f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  // Test for possible error flags
154674f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  if (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS){
154774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    SLOGE("Encryption process is partway completed\n");
154874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    return CRYPTO_COMPLETE_PARTIAL;
154974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  }
155074f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
155174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  if (crypt_ftr.flags & CRYPT_INCONSISTENT_STATE){
155274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    SLOGE("Encryption process was interrupted but cannot continue\n");
155374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    return CRYPTO_COMPLETE_INCONSISTENT;
155474f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  }
155574f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
155674f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  if (crypt_ftr.flags & CRYPT_DATA_CORRUPT){
155774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    SLOGE("Encryption is successful but data is corrupt\n");
155874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    return CRYPTO_COMPLETE_CORRUPT;
15597f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall  }
15607f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall
15617f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall  /* We passed the test! We shall diminish, and return to the west */
156274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  return CRYPTO_COMPLETE_ENCRYPTED;
15637f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall}
15647f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall
1565f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrencestatic int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
15664375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang                                   const char *passwd, const char *mount_point, const char *label)
15678f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
15688f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  /* Allocate enough space for a 256 bit key, but we may use less */
1569160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall  unsigned char decrypted_master_key[32];
15708f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  char crypto_blkdev[MAXPATHLEN];
15718f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  char real_blkdev[MAXPATHLEN];
15728f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  char tmp_mount_point[64];
15738f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  unsigned int orig_failed_decrypt_count;
15748f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  int rc;
157569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence  int use_keymaster = 0;
157669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence  int upgrade = 0;
1577d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence  unsigned char* intermediate_key = 0;
1578d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence  size_t intermediate_key_size = 0;
15794375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang  int N = 1 << crypt_ftr->N_factor;
15804375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang  int r = 1 << crypt_ftr->r_factor;
15814375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang  int p = 1 << crypt_ftr->p_factor;
15828f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1583f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence  SLOGD("crypt_ftr->fs_size = %lld\n", crypt_ftr->fs_size);
1584f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence  orig_failed_decrypt_count = crypt_ftr->failed_decrypt_count;
15850cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall
1586f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence  if (! (crypt_ftr->flags & CRYPT_MNT_KEY_UNENCRYPTED) ) {
1587d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    if (decrypt_master_key(passwd, decrypted_master_key, crypt_ftr,
1588d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence                           &intermediate_key, &intermediate_key_size)) {
15897bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall      SLOGE("Failed to decrypt master key\n");
1590d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence      rc = -1;
1591d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence      goto errout;
15927bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall    }
15938f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
15948f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1595f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence  fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
1596f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
159774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  // Create crypto block device - all (non fatal) code paths
159874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  // need it
1599f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence  if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
1600f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                            real_blkdev, crypto_blkdev, label)) {
160174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence     SLOGE("Error creating decrypted block device\n");
160274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence     rc = -1;
160374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence     goto errout;
16048f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
16058f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
160674f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  /* Work out if the problem is the password or the data */
160774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  unsigned char scrypted_intermediate_key[sizeof(crypt_ftr->
160874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence                                                 scrypted_intermediate_key)];
160974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
161074f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  rc = crypto_scrypt(intermediate_key, intermediate_key_size,
161174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence                     crypt_ftr->salt, sizeof(crypt_ftr->salt),
161274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence                     N, r, p, scrypted_intermediate_key,
161374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence                     sizeof(scrypted_intermediate_key));
161474f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
161574f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  // Does the key match the crypto footer?
161674f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  if (rc == 0 && memcmp(scrypted_intermediate_key,
161774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence                        crypt_ftr->scrypted_intermediate_key,
161874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence                        sizeof(scrypted_intermediate_key)) == 0) {
161974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    SLOGI("Password matches");
162074f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    rc = 0;
162174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  } else {
162274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    /* Try mounting the file system anyway, just in case the problem's with
162374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence     * the footer, not the key. */
1624605d7ae18d6e33b5dc1f6bb813ae32781498a4cdGeorge Burgess IV    snprintf(tmp_mount_point, sizeof(tmp_mount_point), "%s/tmp_mnt",
1625605d7ae18d6e33b5dc1f6bb813ae32781498a4cdGeorge Burgess IV             mount_point);
162674f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    mkdir(tmp_mount_point, 0755);
162774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    if (fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, tmp_mount_point)) {
162874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      SLOGE("Error temp mounting decrypted block device\n");
162974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      delete_crypto_blk_dev(label);
1630d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence
1631d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence      rc = ++crypt_ftr->failed_decrypt_count;
1632d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence      put_crypt_ftr_and_key(crypt_ftr);
163374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    } else {
163474f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      /* Success! */
163574f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      SLOGI("Password did not match but decrypted drive mounted - continue");
163674f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      umount(tmp_mount_point);
163774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence      rc = 0;
1638d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    }
163974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  }
164074f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence
164174f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence  if (rc == 0) {
164274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    crypt_ftr->failed_decrypt_count = 0;
164372b8b82780c062f48350d743c5ee43ced369507dPaul Lawrence    if (orig_failed_decrypt_count != 0) {
164472b8b82780c062f48350d743c5ee43ced369507dPaul Lawrence      put_crypt_ftr_and_key(crypt_ftr);
164572b8b82780c062f48350d743c5ee43ced369507dPaul Lawrence    }
16468f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1647d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    /* Save the name of the crypto block device
164874f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence     * so we can mount it when restarting the framework. */
16496864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall    property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev);
165070a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks
165170a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks    /* Also save a the master key so we can reencrypted the key
165274f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence     * the key when we want to change the password on it. */
165370a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks    memcpy(saved_master_key, decrypted_master_key, KEY_LEN_BYTES);
16543ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    saved_mount_point = strdup(mount_point);
165570a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks    master_key_saved = 1;
16567bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall    SLOGD("%s(): Master key saved\n", __FUNCTION__);
16576864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall    rc = 0;
165869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
165974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    // Upgrade if we're not using the latest KDF.
166069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    use_keymaster = keymaster_check_compatibility();
166169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    if (crypt_ftr->kdf_type == KDF_SCRYPT_KEYMASTER) {
166247ba10d6d53e0d2e54453fe62324afdfa8d6c78aShawn Willden        // Don't allow downgrade
166369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    } else if (use_keymaster == 1 && crypt_ftr->kdf_type != KDF_SCRYPT_KEYMASTER) {
166469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        crypt_ftr->kdf_type = KDF_SCRYPT_KEYMASTER;
166569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        upgrade = 1;
166669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    } else if (use_keymaster == 0 && crypt_ftr->kdf_type != KDF_SCRYPT) {
1667f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        crypt_ftr->kdf_type = KDF_SCRYPT;
166869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        upgrade = 1;
166969f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    }
167069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
167169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    if (upgrade) {
1672f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        rc = encrypt_master_key(passwd, crypt_ftr->salt, saved_master_key,
1673f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                                crypt_ftr->master_key, crypt_ftr);
16747bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall        if (!rc) {
1675f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            rc = put_crypt_ftr_and_key(crypt_ftr);
16767bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall        }
16777bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall        SLOGD("Key Derivation Function upgrade: rc=%d\n", rc);
1678b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence
1679b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence        // Do not fail even if upgrade failed - machine is bootable
1680b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence        // Note that if this code is ever hit, there is a *serious* problem
1681b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence        // since KDFs should never fail. You *must* fix the kdf before
1682b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence        // proceeding!
1683b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence        if (rc) {
1684b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence          SLOGW("Upgrade failed with error %d,"
1685b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence                " but continuing with previous state",
1686b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence                rc);
1687b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence          rc = 0;
1688b2f682bda8443fb93ab67f19be84fd80d5ed2838Paul Lawrence        }
16897bdfa52d934465e2182e2f1c200c4d8581ad5da6JP Abgrall    }
16908f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  }
16918f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1692d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence errout:
1693d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence  if (intermediate_key) {
1694d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    memset(intermediate_key, 0, intermediate_key_size);
1695d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    free(intermediate_key);
1696d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence  }
16978f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall  return rc;
16988f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
16998f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
170029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall/*
17019c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey * Called by vold when it's asked to mount an encrypted external
17029c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey * storage volume. The incoming partition has no crypto header/footer,
17039c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey * as any metadata is been stored in a separate, small partition.
17049c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey *
17059c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey * out_crypto_blkdev must be MAXPATHLEN.
170629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall */
17079c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeyint cryptfs_setup_ext_volume(const char* label, const char* real_blkdev,
17089c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        const unsigned char* key, int keysize, char* out_crypto_blkdev) {
1709ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    int fd = open(real_blkdev, O_RDONLY|O_CLOEXEC);
171014eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    if (fd == -1) {
17119c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        SLOGE("Failed to open %s: %s", real_blkdev, strerror(errno));
171214eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa        return -1;
171314eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    }
171414eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa
171514eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    unsigned long nr_sec = 0;
171614eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    get_blkdev_size(fd, &nr_sec);
171729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    close(fd);
171814eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa
171929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    if (nr_sec == 0) {
17209c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        SLOGE("Failed to get size of %s: %s", real_blkdev, strerror(errno));
172129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        return -1;
172229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
172329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
17249c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    struct crypt_mnt_ftr ext_crypt_ftr;
17259c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    memset(&ext_crypt_ftr, 0, sizeof(ext_crypt_ftr));
17269c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    ext_crypt_ftr.fs_size = nr_sec;
17279c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    ext_crypt_ftr.keysize = keysize;
17289c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    strcpy((char*) ext_crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256");
172929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
17309c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    return create_crypto_blk_dev(&ext_crypt_ftr, key, real_blkdev,
17319c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            out_crypto_blkdev, label);
17329c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey}
173329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
17349c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey/*
17359c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey * Called by vold when it's asked to unmount an encrypted external
17369c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey * storage volume.
17379c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey */
17389c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeyint cryptfs_revert_ext_volume(const char* label) {
17399c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    return delete_crypto_blk_dev((char*) label);
174029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
174129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
17427f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrallint cryptfs_crypto_complete(void)
17437f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall{
17447f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall  return do_crypto_complete("/data");
17457f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall}
17467f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall
1747f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrenceint check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr)
1748f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence{
1749f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    char encrypted_state[PROPERTY_VALUE_MAX];
1750f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    property_get("ro.crypto.state", encrypted_state, "");
1751f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) {
1752f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGE("encrypted fs already validated or not running with encryption,"
1753f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence              " aborting");
1754f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        return -1;
1755f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    }
1756f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
1757f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    if (get_crypt_ftr_and_key(crypt_ftr)) {
1758f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGE("Error getting crypt footer and key");
1759f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        return -1;
1760f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    }
1761f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
1762f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    return 0;
1763f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence}
1764f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
17654375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wangint cryptfs_check_passwd(const char *passwd)
17668f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
176705335c344d73411439774dfa548c633020e158e1Paul Lawrence    SLOGI("cryptfs_check_passwd");
176838132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (e4crypt_is_native()) {
17697b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        SLOGE("cryptfs_check_passwd not valid for file encryption");
17707b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        return -1;
177105335c344d73411439774dfa548c633020e158e1Paul Lawrence    }
177205335c344d73411439774dfa548c633020e158e1Paul Lawrence
1773f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    struct crypt_mnt_ftr crypt_ftr;
1774f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    int rc;
17758f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
1776f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    rc = check_unmounted_and_get_ftr(&crypt_ftr);
17773d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (rc) {
17783d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        SLOGE("Could not get footer");
1779f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        return rc;
17803d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    }
17818f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
17823bd36d5e5f14dff4dadba88eb27664e495d0e16ePaul Lawrence    rc = test_mount_encrypted_fs(&crypt_ftr, passwd,
17833d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                                 DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
17843d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (rc) {
17853d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        SLOGE("Password did not match");
17863d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        return rc;
17873d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    }
17883d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
17893d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (crypt_ftr.flags & CRYPT_FORCE_COMPLETE) {
17903d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        // Here we have a default actual password but a real password
17913d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        // we must test against the scrypted value
17923d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        // First, we must delete the crypto block device that
17933d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        // test_mount_encrypted_fs leaves behind as a side effect
17943d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        delete_crypto_blk_dev(CRYPTO_BLOCK_DEVICE);
17953d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        rc = test_mount_encrypted_fs(&crypt_ftr, DEFAULT_PASSWORD,
17963d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                                     DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
17973d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        if (rc) {
17983d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            SLOGE("Default password did not match on reboot encryption");
17993d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            return rc;
18003d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        }
18013d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
18023d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        crypt_ftr.flags &= ~CRYPT_FORCE_COMPLETE;
18033d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        put_crypt_ftr_and_key(&crypt_ftr);
18043d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        rc = cryptfs_changepw(crypt_ftr.crypt_type, passwd);
18053d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        if (rc) {
18063d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            SLOGE("Could not change password on reboot encryption");
18073d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            return rc;
18083d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        }
18093d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    }
1810684dbdf316a02cf6a7694018f7c3a4bcd65142ccPaul Lawrence
18113d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) {
1812399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        cryptfs_clear_password();
1813399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        password = strdup(passwd);
1814399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        struct timespec now;
1815399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        clock_gettime(CLOCK_BOOTTIME, &now);
1816399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        password_expiry_time = now.tv_sec + password_max_age_seconds;
1817684dbdf316a02cf6a7694018f7c3a4bcd65142ccPaul Lawrence    }
1818684dbdf316a02cf6a7694018f7c3a4bcd65142ccPaul Lawrence
18198f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return rc;
18208f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
18218f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
18223ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrallint cryptfs_verify_passwd(char *passwd)
18233ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall{
18243ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    struct crypt_mnt_ftr crypt_ftr;
18253ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    /* Allocate enough space for a 256 bit key, but we may use less */
1826160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    unsigned char decrypted_master_key[32];
18273ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    char encrypted_state[PROPERTY_VALUE_MAX];
18283ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    int rc;
18293ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall
18303ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    property_get("ro.crypto.state", encrypted_state, "");
18313ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    if (strcmp(encrypted_state, "encrypted") ) {
18323ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        SLOGE("device not encrypted, aborting");
18333ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        return -2;
18343ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    }
18353ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall
18363ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    if (!master_key_saved) {
18373ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        SLOGE("encrypted fs not yet mounted, aborting");
18383ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        return -1;
18393ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    }
18403ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall
18413ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    if (!saved_mount_point) {
18423ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        SLOGE("encrypted fs failed to save mount point, aborting");
18433ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        return -1;
18443ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    }
18453ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall
1846160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (get_crypt_ftr_and_key(&crypt_ftr)) {
18473ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        SLOGE("Error getting crypt footer and key\n");
18483ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        return -1;
18493ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    }
18503ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall
18513ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    if (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) {
18523ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        /* If the device has no password, then just say the password is valid */
18533ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        rc = 0;
18543ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    } else {
1855d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence        decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
18563ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        if (!memcmp(decrypted_master_key, saved_master_key, crypt_ftr.keysize)) {
18573ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall            /* They match, the password is correct */
18583ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall            rc = 0;
18593ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        } else {
18603ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall            /* If incorrect, sleep for a bit to prevent dictionary attacks */
18613ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall            sleep(1);
18623ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall            rc = 1;
18633ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        }
18643ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    }
18653ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall
18663ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    return rc;
18673ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall}
18683ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall
18698f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall/* Initialize a crypt_mnt_ftr structure.  The keysize is
18708f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * defaulted to 16 bytes, and the filesystem size to 0.
18718f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * Presumably, at a minimum, the caller will update the
18728f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall * filesystem size and crypto_type_name after calling this function.
18738f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall */
187469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrencestatic int cryptfs_init_crypt_mnt_ftr(struct crypt_mnt_ftr *ftr)
18758f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
1876160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    off64_t off;
1877160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
1878160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    memset(ftr, 0, sizeof(struct crypt_mnt_ftr));
18798f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    ftr->magic = CRYPT_MNT_MAGIC;
1880c96a5f8edf65a8abe441d0cfd3ce227bdf1bf55fKenny Root    ftr->major_version = CURRENT_MAJOR_VERSION;
1881c96a5f8edf65a8abe441d0cfd3ce227bdf1bf55fKenny Root    ftr->minor_version = CURRENT_MINOR_VERSION;
18828f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    ftr->ftr_size = sizeof(struct crypt_mnt_ftr);
188370a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks    ftr->keysize = KEY_LEN_BYTES;
1884160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
188569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    switch (keymaster_check_compatibility()) {
188669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    case 1:
188769f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        ftr->kdf_type = KDF_SCRYPT_KEYMASTER;
188869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        break;
188969f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
189069f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    case 0:
189169f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        ftr->kdf_type = KDF_SCRYPT;
189269f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        break;
189369f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
189469f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    default:
189569f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        SLOGE("keymaster_check_compatibility failed");
189669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        return -1;
189769f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    }
189869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
1899c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root    get_device_scrypt_params(ftr);
1900c4c70f15bb8845b02f9ec1d624794757badd6933Kenny Root
1901160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    ftr->persist_data_size = CRYPT_PERSIST_DATA_SIZE;
1902160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (get_crypt_ftr_info(NULL, &off) == 0) {
1903160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        ftr->persist_data_offset[0] = off + CRYPT_FOOTER_TO_PERSIST_OFFSET;
1904160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        ftr->persist_data_offset[1] = off + CRYPT_FOOTER_TO_PERSIST_OFFSET +
1905160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall                                    ftr->persist_data_size;
1906160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
190769f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence
190869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence    return 0;
19098f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
19108f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
191129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallstatic int cryptfs_enable_wipe(char *crypto_blkdev, off64_t size, int type)
19128f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
1913e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall    const char *args[10];
1914e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall    char size_str[32]; /* Must be large enough to hold a %lld and null byte */
1915e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall    int num_args;
1916e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall    int status;
1917e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall    int tmp;
19188f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    int rc = -1;
19198f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
192029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    if (type == EXT4_FS) {
1921e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht#ifdef TARGET_USES_MKE2FS
1922e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        args[0] = "/system/bin/mke2fs";
1923e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        args[1] = "-M";
1924e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        args[2] = "/data";
1925e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        args[3] = "-b";
1926e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        args[4] = "4096";
1927e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        args[5] = "-t";
1928e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        args[6] = "ext4";
1929e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        args[7] = crypto_blkdev;
1930e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        snprintf(size_str, sizeof(size_str), "%" PRId64, size / (4096 / 512));
1931e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        args[8] = size_str;
1932e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht        num_args = 9;
1933e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht#else
1934e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        args[0] = "/system/bin/make_ext4fs";
1935e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        args[1] = "-a";
1936e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        args[2] = "/data";
1937e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        args[3] = "-l";
19387373716c6d65ca328de11c994c60f698a9ef6290Elliott Hughes        snprintf(size_str, sizeof(size_str), "%" PRId64, size * 512);
1939e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        args[4] = size_str;
1940e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        args[5] = crypto_blkdev;
1941e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        num_args = 6;
1942e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht#endif
1943e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        SLOGI("Making empty filesystem with command %s %s %s %s %s %s\n",
1944e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall              args[0], args[1], args[2], args[3], args[4], args[5]);
194562c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall    } else if (type == F2FS_FS) {
194662c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        args[0] = "/system/bin/mkfs.f2fs";
194762c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        args[1] = "-t";
194862c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        args[2] = "-d1";
194962c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        args[3] = crypto_blkdev;
19507373716c6d65ca328de11c994c60f698a9ef6290Elliott Hughes        snprintf(size_str, sizeof(size_str), "%" PRId64, size);
195162c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        args[4] = size_str;
195262c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        num_args = 5;
195362c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        SLOGI("Making empty filesystem with command %s %s %s %s %s\n",
195462c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall              args[0], args[1], args[2], args[3], args[4]);
195529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    } else {
195629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        SLOGE("cryptfs_enable_wipe(): unknown filesystem type %d\n", type);
195729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        return -1;
195829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
195929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
1960e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall    tmp = android_fork_execvp(num_args, (char **)args, &status, false, true);
1961e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall
1962e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall    if (tmp != 0) {
1963e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall      SLOGE("Error creating empty filesystem on %s due to logwrap error\n", crypto_blkdev);
19648f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    } else {
1965e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        if (WIFEXITED(status)) {
1966e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall            if (WEXITSTATUS(status)) {
1967e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall                SLOGE("Error creating filesystem on %s, exit status %d ",
1968e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall                      crypto_blkdev, WEXITSTATUS(status));
1969e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall            } else {
1970e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall                SLOGD("Successfully created filesystem on %s\n", crypto_blkdev);
1971e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall                rc = 0;
1972e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall            }
1973e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall        } else {
1974e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall            SLOGE("Error creating filesystem on %s, did not exit normally\n", crypto_blkdev);
1975e550f78a3ff5985ba21cac263629c957500ef4e4Ken Sumrall       }
19768f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
19778f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
19788f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return rc;
19798f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
19808f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
19818f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#define CRYPT_INPLACE_BUFSIZE 4096
198287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence#define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / CRYPT_SECTOR_SIZE)
198387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence#define CRYPT_SECTOR_SIZE 512
1984ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
1985ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence/* aligned 32K writes tends to make flash happy.
1986ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence * SD card association recommends it.
1987ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence */
1988ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence#define BLOCKS_AT_A_TIME 8
1989ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
1990ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrencestruct encryptGroupsData
1991ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence{
1992ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    int realfd;
1993ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    int cryptofd;
1994ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    off64_t numblocks;
1995ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    off64_t one_pct, cur_pct, new_pct;
1996ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    off64_t blocks_already_done, tot_numblocks;
199758c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    off64_t used_blocks_already_done, tot_used_blocks;
1998ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    char* real_blkdev, * crypto_blkdev;
1999ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    int count;
2000ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    off64_t offset;
2001ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    char* buffer;
200287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    off64_t last_written_sector;
200387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    int completed;
2004a96d9c9b3861506003930d4dbdc669173bf9a50ePaul Lawrence    time_t time_started;
2005a96d9c9b3861506003930d4dbdc669173bf9a50ePaul Lawrence    int remaining_time;
2006ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence};
2007ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
200858c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrencestatic void update_progress(struct encryptGroupsData* data, int is_used)
2009ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence{
2010ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    data->blocks_already_done++;
201158c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence
201258c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    if (is_used) {
201358c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence        data->used_blocks_already_done++;
201458c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    }
201558c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    if (data->tot_used_blocks) {
201658c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence        data->new_pct = data->used_blocks_already_done / data->one_pct;
201758c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    } else {
201858c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence        data->new_pct = data->blocks_already_done / data->one_pct;
201958c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    }
202058c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence
2021ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    if (data->new_pct > data->cur_pct) {
2022ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        char buf[8];
2023ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        data->cur_pct = data->new_pct;
2024cb33f5741cd37c93f7f1888a3dcbabdfab1524a9Elliott Hughes        snprintf(buf, sizeof(buf), "%" PRId64, data->cur_pct);
2025ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        property_set("vold.encrypt_progress", buf);
2026ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2027a96d9c9b3861506003930d4dbdc669173bf9a50ePaul Lawrence
2028a96d9c9b3861506003930d4dbdc669173bf9a50ePaul Lawrence    if (data->cur_pct >= 5) {
20299c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence        struct timespec time_now;
20309c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence        if (clock_gettime(CLOCK_MONOTONIC, &time_now)) {
20319c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence            SLOGW("Error getting time");
20329c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence        } else {
20339c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence            double elapsed_time = difftime(time_now.tv_sec, data->time_started);
20349c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence            off64_t remaining_blocks = data->tot_used_blocks
20359c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence                                       - data->used_blocks_already_done;
20369c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence            int remaining_time = (int)(elapsed_time * remaining_blocks
20379c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence                                       / data->used_blocks_already_done);
20389c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence
20399c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence            // Change time only if not yet set, lower, or a lot higher for
20409c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence            // best user experience
20419c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence            if (data->remaining_time == -1
20429c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence                || remaining_time < data->remaining_time
20439c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence                || remaining_time > data->remaining_time + 60) {
20449c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence                char buf[8];
20459c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence                snprintf(buf, sizeof(buf), "%d", remaining_time);
20469c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence                property_set("vold.encrypt_time_remaining", buf);
20479c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence                data->remaining_time = remaining_time;
20489c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence            }
2049a96d9c9b3861506003930d4dbdc669173bf9a50ePaul Lawrence        }
2050a96d9c9b3861506003930d4dbdc669173bf9a50ePaul Lawrence    }
2051ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence}
2052ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
20533846be17feba13150a5db22204622db6a762a0d8Paul Lawrencestatic void log_progress(struct encryptGroupsData const* data, bool completed)
20543846be17feba13150a5db22204622db6a762a0d8Paul Lawrence{
20553846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Precondition - if completed data = 0 else data != 0
20563846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
20573846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Track progress so we can skip logging blocks
20583846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    static off64_t offset = -1;
20593846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
20603846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Need to close existing 'Encrypting from' log?
20613846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    if (completed || (offset != -1 && data->offset != offset)) {
20623846be17feba13150a5db22204622db6a762a0d8Paul Lawrence        SLOGI("Encrypted to sector %" PRId64,
20633846be17feba13150a5db22204622db6a762a0d8Paul Lawrence              offset / info.block_size * CRYPT_SECTOR_SIZE);
20643846be17feba13150a5db22204622db6a762a0d8Paul Lawrence        offset = -1;
20653846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    }
20663846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
20673846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Need to start new 'Encrypting from' log?
20683846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    if (!completed && offset != data->offset) {
20693846be17feba13150a5db22204622db6a762a0d8Paul Lawrence        SLOGI("Encrypting from sector %" PRId64,
20703846be17feba13150a5db22204622db6a762a0d8Paul Lawrence              data->offset / info.block_size * CRYPT_SECTOR_SIZE);
20713846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    }
20723846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
20733846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Update offset
20743846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    if (!completed) {
20753846be17feba13150a5db22204622db6a762a0d8Paul Lawrence        offset = data->offset + (off64_t)data->count * info.block_size;
20763846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    }
20773846be17feba13150a5db22204622db6a762a0d8Paul Lawrence}
20783846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
2079ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrencestatic int flush_outstanding_data(struct encryptGroupsData* data)
2080ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence{
2081ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    if (data->count == 0) {
2082ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        return 0;
2083ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2084ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2085231bdba012fd7e6d545d8ba67b32e49a66ec52e0Elliott Hughes    SLOGV("Copying %d blocks at offset %" PRIx64, data->count, data->offset);
2086ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2087ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    if (pread64(data->realfd, data->buffer,
2088ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                info.block_size * data->count, data->offset)
2089ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        <= 0) {
2090ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        SLOGE("Error reading real_blkdev %s for inplace encrypt",
2091ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence              data->real_blkdev);
2092ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        return -1;
2093ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2094ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2095ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    if (pwrite64(data->cryptofd, data->buffer,
2096ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                 info.block_size * data->count, data->offset)
2097ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        <= 0) {
2098ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        SLOGE("Error writing crypto_blkdev %s for inplace encrypt",
2099ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence              data->crypto_blkdev);
2100ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        return -1;
210187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    } else {
21023846be17feba13150a5db22204622db6a762a0d8Paul Lawrence      log_progress(data, false);
2103ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2104ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2105ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    data->count = 0;
210687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    data->last_written_sector = (data->offset + data->count)
210787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                / info.block_size * CRYPT_SECTOR_SIZE - 1;
2108ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    return 0;
2109ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence}
2110ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2111ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrencestatic int encrypt_groups(struct encryptGroupsData* data)
2112ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence{
2113ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    unsigned int i;
2114ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    u8 *block_bitmap = 0;
2115ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    unsigned int block;
2116ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    off64_t ret;
2117ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    int rc = -1;
2118ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
21194375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    data->buffer = (char *)malloc(info.block_size * BLOCKS_AT_A_TIME);
2120ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    if (!data->buffer) {
2121ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        SLOGE("Failed to allocate crypto buffer");
2122ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        goto errout;
2123ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2124ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
21254375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    block_bitmap = (u8 *)malloc(info.block_size);
2126ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    if (!block_bitmap) {
2127ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        SLOGE("failed to allocate block bitmap");
2128ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        goto errout;
2129ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2130ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2131ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    for (i = 0; i < aux_info.groups; ++i) {
2132ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        SLOGI("Encrypting group %d", i);
2133ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2134ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        u32 first_block = aux_info.first_data_block + i * info.blocks_per_group;
21354375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang        u32 block_count = std::min(info.blocks_per_group,
21364375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang                                   (u32)(aux_info.len_blocks - first_block));
2137ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2138ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        off64_t offset = (u64)info.block_size
2139ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                         * aux_info.bg_desc[i].bg_block_bitmap;
2140ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2141ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        ret = pread64(data->realfd, block_bitmap, info.block_size, offset);
2142ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        if (ret != (int)info.block_size) {
2143ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence            SLOGE("failed to read all of block group bitmap %d", i);
2144ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence            goto errout;
2145ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        }
2146ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2147ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        offset = (u64)info.block_size * first_block;
2148ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2149ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        data->count = 0;
2150ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2151ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        for (block = 0; block < block_count; block++) {
2152aa08e58e3a5d66bf3714c537336337b766458d9fliminghao            int used = (aux_info.bg_desc[i].bg_flags & EXT4_BG_BLOCK_UNINIT) ?
2153aa08e58e3a5d66bf3714c537336337b766458d9fliminghao                    0 : bitmap_get_bit(block_bitmap, block);
215458c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence            update_progress(data, used);
215558c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence            if (used) {
2156ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                if (data->count == 0) {
2157ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                    data->offset = offset;
2158ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                }
2159ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                data->count++;
2160ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence            } else {
2161ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                if (flush_outstanding_data(data)) {
2162ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                    goto errout;
2163ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                }
2164ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence            }
2165ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2166ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence            offset += info.block_size;
2167ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2168ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence            /* Write data if we are aligned or buffer size reached */
2169ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence            if (offset % (info.block_size * BLOCKS_AT_A_TIME) == 0
2170ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                || data->count == BLOCKS_AT_A_TIME) {
2171ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                if (flush_outstanding_data(data)) {
2172ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                    goto errout;
2173ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                }
2174ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence            }
217587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
217673d7a02dc6e18b4c0a6f29e8f89b432c1b6cc808Paul Lawrence            if (!is_battery_ok_to_continue()) {
217787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                SLOGE("Stopping encryption due to low battery");
217887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                rc = 0;
217987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                goto errout;
218087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            }
218187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
2182ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        }
2183ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        if (flush_outstanding_data(data)) {
2184ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence            goto errout;
2185ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        }
2186ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2187ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
218887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    data->completed = 1;
2189ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    rc = 0;
2190ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2191ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrenceerrout:
21923846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    log_progress(0, true);
2193ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    free(data->buffer);
2194ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    free(block_bitmap);
2195ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    return rc;
2196ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence}
2197ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2198ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrencestatic int cryptfs_enable_inplace_ext4(char *crypto_blkdev,
2199ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                                       char *real_blkdev,
2200ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                                       off64_t size,
2201ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                                       off64_t *size_already_done,
220287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                       off64_t tot_size,
220387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                       off64_t previously_encrypted_upto)
2204ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence{
220558c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    u32 i;
2206ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    struct encryptGroupsData data;
220774f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence    int rc; // Can't initialize without causing warning -Wclobbered
22084375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    struct timespec time_started = {0};
22094375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    int retries = RETRY_MOUNT_ATTEMPTS;
2210ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
221187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (previously_encrypted_upto > *size_already_done) {
221287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        SLOGD("Not fast encrypting since resuming part way through");
221387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        return -1;
221487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
221587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
2216ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    memset(&data, 0, sizeof(data));
2217ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    data.real_blkdev = real_blkdev;
2218ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    data.crypto_blkdev = crypto_blkdev;
2219ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2220ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if ( (data.realfd = open(real_blkdev, O_RDWR|O_CLOEXEC)) < 0) {
22213334c6a1ae38b2c7886fc9c0a69467e586af8635JP Abgrall        SLOGE("Error opening real_blkdev %s for inplace encrypt. err=%d(%s)\n",
22223334c6a1ae38b2c7886fc9c0a69467e586af8635JP Abgrall              real_blkdev, errno, strerror(errno));
222374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        rc = -1;
2224ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        goto errout;
2225ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2226ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
222782fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng    // Wait until the block device appears.  Re-use the mount retry values since it is reasonable.
222882fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng    while ((data.cryptofd = open(crypto_blkdev, O_WRONLY|O_CLOEXEC)) < 0) {
222982fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng        if (--retries) {
223082fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng            SLOGE("Error opening crypto_blkdev %s for ext4 inplace encrypt. err=%d(%s), retrying\n",
223182fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng                  crypto_blkdev, errno, strerror(errno));
223282fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng            sleep(RETRY_MOUNT_DELAY_SECONDS);
223382fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng        } else {
223482fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng            SLOGE("Error opening crypto_blkdev %s for ext4 inplace encrypt. err=%d(%s)\n",
223582fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng                  crypto_blkdev, errno, strerror(errno));
223682fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng            rc = ENABLE_INPLACE_ERR_DEV;
223782fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng            goto errout;
223882fd804f8ba49399f425bf43681b9b7fe464d9a1David Ng        }
2239ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2240ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2241ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    if (setjmp(setjmp_env)) {
22427fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        SLOGE("Reading ext4 extent caused an exception\n");
224374f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        rc = -1;
2244ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        goto errout;
2245ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2246ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2247ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    if (read_ext(data.realfd, 0) != 0) {
22487fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        SLOGE("Failed to read ext4 extent\n");
224974f29f1df7d12c0cc06e9d6685adf15e757d8edaPaul Lawrence        rc = -1;
2250ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        goto errout;
2251ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2252ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2253ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    data.numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
2254ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    data.tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
2255ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    data.blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
2256ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
22577fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    SLOGI("Encrypting ext4 filesystem in place...");
2258ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
225958c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    data.tot_used_blocks = data.numblocks;
226058c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    for (i = 0; i < aux_info.groups; ++i) {
226158c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence      data.tot_used_blocks -= aux_info.bg_desc[i].bg_free_blocks_count;
226258c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    }
226358c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence
226458c58cf7ef922ef019ce78ce1c418a7643c39518Paul Lawrence    data.one_pct = data.tot_used_blocks / 100;
2265ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    data.cur_pct = 0;
22669c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence
22679c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence    if (clock_gettime(CLOCK_MONOTONIC, &time_started)) {
22689c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence        SLOGW("Error getting time at start");
22699c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence        // Note - continue anyway - we'll run with 0
22709c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence    }
22719c58a871f9fb356409d3b90734bf706d1463f041Paul Lawrence    data.time_started = time_started.tv_sec;
2272a96d9c9b3861506003930d4dbdc669173bf9a50ePaul Lawrence    data.remaining_time = -1;
2273ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2274ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    rc = encrypt_groups(&data);
2275ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    if (rc) {
2276ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        SLOGE("Error encrypting groups");
2277ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence        goto errout;
2278ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
2279ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
228087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    *size_already_done += data.completed ? size : data.last_written_sector;
2281ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    rc = 0;
2282ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2283ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrenceerrout:
2284ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    close(data.realfd);
2285ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    close(data.cryptofd);
2286ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
2287ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    return rc;
2288ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence}
2289ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
22903846be17feba13150a5db22204622db6a762a0d8Paul Lawrencestatic void log_progress_f2fs(u64 block, bool completed)
22913846be17feba13150a5db22204622db6a762a0d8Paul Lawrence{
22923846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Precondition - if completed data = 0 else data != 0
22933846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
22943846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Track progress so we can skip logging blocks
22953846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    static u64 last_block = (u64)-1;
22963846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
22973846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Need to close existing 'Encrypting from' log?
22983846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    if (completed || (last_block != (u64)-1 && block != last_block + 1)) {
22993846be17feba13150a5db22204622db6a762a0d8Paul Lawrence        SLOGI("Encrypted to block %" PRId64, last_block);
23003846be17feba13150a5db22204622db6a762a0d8Paul Lawrence        last_block = -1;
23013846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    }
23023846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
23033846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Need to start new 'Encrypting from' log?
23043846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    if (!completed && (last_block == (u64)-1 || block != last_block + 1)) {
23053846be17feba13150a5db22204622db6a762a0d8Paul Lawrence        SLOGI("Encrypting from block %" PRId64, block);
23063846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    }
23073846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
23083846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    // Update offset
23093846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    if (!completed) {
23103846be17feba13150a5db22204622db6a762a0d8Paul Lawrence        last_block = block;
23113846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    }
23123846be17feba13150a5db22204622db6a762a0d8Paul Lawrence}
23133846be17feba13150a5db22204622db6a762a0d8Paul Lawrence
2314e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenbergstatic int encrypt_one_block_f2fs(u64 pos, void *data)
2315e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg{
2316e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    struct encryptGroupsData *priv_dat = (struct encryptGroupsData *)data;
2317e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2318e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    priv_dat->blocks_already_done = pos - 1;
2319e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    update_progress(priv_dat, 1);
2320e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2321e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    off64_t offset = pos * CRYPT_INPLACE_BUFSIZE;
2322e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2323e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    if (pread64(priv_dat->realfd, priv_dat->buffer, CRYPT_INPLACE_BUFSIZE, offset) <= 0) {
23247fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        SLOGE("Error reading real_blkdev %s for f2fs inplace encrypt", priv_dat->crypto_blkdev);
2325e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        return -1;
2326e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    }
2327e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2328e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    if (pwrite64(priv_dat->cryptofd, priv_dat->buffer, CRYPT_INPLACE_BUFSIZE, offset) <= 0) {
23297fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        SLOGE("Error writing crypto_blkdev %s for f2fs inplace encrypt", priv_dat->crypto_blkdev);
2330e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        return -1;
2331e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    } else {
23323846be17feba13150a5db22204622db6a762a0d8Paul Lawrence        log_progress_f2fs(pos, false);
2333e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    }
2334e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2335e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    return 0;
2336e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg}
2337e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2338e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenbergstatic int cryptfs_enable_inplace_f2fs(char *crypto_blkdev,
2339e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg                                       char *real_blkdev,
2340e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg                                       off64_t size,
2341e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg                                       off64_t *size_already_done,
2342e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg                                       off64_t tot_size,
2343e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg                                       off64_t previously_encrypted_upto)
2344e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg{
2345e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    struct encryptGroupsData data;
2346e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    struct f2fs_info *f2fs_info = NULL;
23477fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    int rc = ENABLE_INPLACE_ERR_OTHER;
2348e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    if (previously_encrypted_upto > *size_already_done) {
2349e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        SLOGD("Not fast encrypting since resuming part way through");
23507fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        return ENABLE_INPLACE_ERR_OTHER;
2351e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    }
2352e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    memset(&data, 0, sizeof(data));
2353e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.real_blkdev = real_blkdev;
2354e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.crypto_blkdev = crypto_blkdev;
2355e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.realfd = -1;
2356e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.cryptofd = -1;
2357ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if ( (data.realfd = open64(real_blkdev, O_RDWR|O_CLOEXEC)) < 0) {
23587fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        SLOGE("Error opening real_blkdev %s for f2fs inplace encrypt\n",
2359e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg              real_blkdev);
2360e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        goto errout;
2361e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    }
2362ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if ( (data.cryptofd = open64(crypto_blkdev, O_WRONLY|O_CLOEXEC)) < 0) {
23637fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        SLOGE("Error opening crypto_blkdev %s for f2fs inplace encrypt. err=%d(%s)\n",
23643334c6a1ae38b2c7886fc9c0a69467e586af8635JP Abgrall              crypto_blkdev, errno, strerror(errno));
23657fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        rc = ENABLE_INPLACE_ERR_DEV;
2366e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        goto errout;
2367e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    }
2368e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2369e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    f2fs_info = generate_f2fs_info(data.realfd);
2370e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    if (!f2fs_info)
2371e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg      goto errout;
2372e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2373e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
2374e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
2375e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
2376e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2377e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.tot_used_blocks = get_num_blocks_used(f2fs_info);
2378e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2379e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.one_pct = data.tot_used_blocks / 100;
2380e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.cur_pct = 0;
2381e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.time_started = time(NULL);
2382e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.remaining_time = -1;
2383e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
23844375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    data.buffer = (char *)malloc(f2fs_info->block_size);
2385e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    if (!data.buffer) {
2386e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        SLOGE("Failed to allocate crypto buffer");
2387e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        goto errout;
2388e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    }
2389e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2390e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    data.count = 0;
2391e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2392e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    /* Currently, this either runs to completion, or hits a nonrecoverable error */
2393e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    rc = run_on_used_blocks(data.blocks_already_done, f2fs_info, &encrypt_one_block_f2fs, &data);
2394e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2395e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    if (rc) {
23967fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        SLOGE("Error in running over f2fs blocks");
23977fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        rc = ENABLE_INPLACE_ERR_OTHER;
2398e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        goto errout;
2399e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    }
2400e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2401e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    *size_already_done += size;
2402e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    rc = 0;
2403e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2404e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenbergerrout:
2405e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    if (rc)
2406e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        SLOGE("Failed to encrypt f2fs filesystem on %s", real_blkdev);
2407e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
24083846be17feba13150a5db22204622db6a762a0d8Paul Lawrence    log_progress_f2fs(0, true);
2409e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    free(f2fs_info);
2410e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    free(data.buffer);
2411e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    close(data.realfd);
2412e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    close(data.cryptofd);
2413e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2414e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    return rc;
2415e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg}
2416e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
2417ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrencestatic int cryptfs_enable_inplace_full(char *crypto_blkdev, char *real_blkdev,
2418ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                                       off64_t size, off64_t *size_already_done,
241987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                       off64_t tot_size,
242087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                       off64_t previously_encrypted_upto)
24218f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
24228f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    int realfd, cryptofd;
24238f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    char *buf[CRYPT_INPLACE_BUFSIZE];
24247fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    int rc = ENABLE_INPLACE_ERR_OTHER;
24258f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    off64_t numblocks, i, remainder;
24268ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    off64_t one_pct, cur_pct, new_pct;
242729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    off64_t blocks_already_done, tot_numblocks;
24288ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
2429ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if ( (realfd = open(real_blkdev, O_RDONLY|O_CLOEXEC)) < 0) {
24308f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        SLOGE("Error opening real_blkdev %s for inplace encrypt\n", real_blkdev);
24317fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        return ENABLE_INPLACE_ERR_OTHER;
24328f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
24338f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
2434ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if ( (cryptofd = open(crypto_blkdev, O_WRONLY|O_CLOEXEC)) < 0) {
24353334c6a1ae38b2c7886fc9c0a69467e586af8635JP Abgrall        SLOGE("Error opening crypto_blkdev %s for inplace encrypt. err=%d(%s)\n",
24363334c6a1ae38b2c7886fc9c0a69467e586af8635JP Abgrall              crypto_blkdev, errno, strerror(errno));
24378f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        close(realfd);
24387fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        return ENABLE_INPLACE_ERR_DEV;
24398f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
24408f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
24418f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    /* This is pretty much a simple loop of reading 4K, and writing 4K.
24428f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall     * The size passed in is the number of 512 byte sectors in the filesystem.
24438f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall     * So compute the number of whole 4K blocks we should read/write,
24448f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall     * and the remainder.
24458f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall     */
24468f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
24478f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    remainder = size % CRYPT_SECTORS_PER_BUFSIZE;
244829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
244929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
24508f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
24518f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    SLOGE("Encrypting filesystem in place...");
24528f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
245387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    i = previously_encrypted_upto + 1 - *size_already_done;
245487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
245587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (lseek64(realfd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) {
245687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        SLOGE("Cannot seek to previously encrypted point on %s", real_blkdev);
245787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        goto errout;
245887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
245987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
246087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (lseek64(cryptofd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) {
246187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        SLOGE("Cannot seek to previously encrypted point on %s", crypto_blkdev);
246287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        goto errout;
246387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
246487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
246587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    for (;i < size && i % CRYPT_SECTORS_PER_BUFSIZE != 0; ++i) {
246687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        if (unix_read(realfd, buf, CRYPT_SECTOR_SIZE) <= 0) {
246787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Error reading initial sectors from real_blkdev %s for "
246887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                  "inplace encrypt\n", crypto_blkdev);
246987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            goto errout;
247087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
247187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        if (unix_write(cryptofd, buf, CRYPT_SECTOR_SIZE) <= 0) {
247287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Error writing initial sectors to crypto_blkdev %s for "
247387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                  "inplace encrypt\n", crypto_blkdev);
247487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            goto errout;
247587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        } else {
2476cb33f5741cd37c93f7f1888a3dcbabdfab1524a9Elliott Hughes            SLOGI("Encrypted 1 block at %" PRId64, i);
247787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
247887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
247987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
248029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    one_pct = tot_numblocks / 100;
24818ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    cur_pct = 0;
24828f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    /* process the majority of the filesystem in blocks */
248387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    for (i/=CRYPT_SECTORS_PER_BUFSIZE; i<numblocks; i++) {
248429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        new_pct = (i + blocks_already_done) / one_pct;
24858ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        if (new_pct > cur_pct) {
24868ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall            char buf[8];
24878ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
24888ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall            cur_pct = new_pct;
2489cb33f5741cd37c93f7f1888a3dcbabdfab1524a9Elliott Hughes            snprintf(buf, sizeof(buf), "%" PRId64, cur_pct);
24908ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall            property_set("vold.encrypt_progress", buf);
24918ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        }
24928f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        if (unix_read(realfd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
249387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Error reading real_blkdev %s for inplace encrypt", crypto_blkdev);
24948f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall            goto errout;
24958f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        }
24968f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        if (unix_write(cryptofd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
249787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Error writing crypto_blkdev %s for inplace encrypt", crypto_blkdev);
249887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            goto errout;
249987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        } else {
2500cb33f5741cd37c93f7f1888a3dcbabdfab1524a9Elliott Hughes            SLOGD("Encrypted %d block at %" PRId64,
250187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                  CRYPT_SECTORS_PER_BUFSIZE,
250287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                  i * CRYPT_SECTORS_PER_BUFSIZE);
250387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
250487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
250573d7a02dc6e18b4c0a6f29e8f89b432c1b6cc808Paul Lawrence       if (!is_battery_ok_to_continue()) {
250687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Stopping encryption due to low battery");
250787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            *size_already_done += (i + 1) * CRYPT_SECTORS_PER_BUFSIZE - 1;
250887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            rc = 0;
25098f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall            goto errout;
25108f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        }
25118f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
25128f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
25138f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    /* Do any remaining sectors */
25148f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    for (i=0; i<remainder; i++) {
251587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        if (unix_read(realfd, buf, CRYPT_SECTOR_SIZE) <= 0) {
251687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Error reading final sectors from real_blkdev %s for inplace encrypt", crypto_blkdev);
25178f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall            goto errout;
25188f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        }
251987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        if (unix_write(cryptofd, buf, CRYPT_SECTOR_SIZE) <= 0) {
252087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Error writing final sectors to crypto_blkdev %s for inplace encrypt", crypto_blkdev);
25218f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall            goto errout;
252287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        } else {
252387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGI("Encrypted 1 block at next location");
25248f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        }
25258f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
25268f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
252729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    *size_already_done += size;
25288f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    rc = 0;
25298f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
25308f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrallerrout:
25318f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    close(realfd);
25328f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    close(cryptofd);
25338f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
25348f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return rc;
25358f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
25368f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
25377fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall/* returns on of the ENABLE_INPLACE_* return codes */
2538ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrencestatic int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev,
2539ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence                                  off64_t size, off64_t *size_already_done,
254087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                  off64_t tot_size,
254187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                  off64_t previously_encrypted_upto)
2542ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence{
25437fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    int rc_ext4, rc_f2fs, rc_full;
254487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (previously_encrypted_upto) {
2545cb33f5741cd37c93f7f1888a3dcbabdfab1524a9Elliott Hughes        SLOGD("Continuing encryption from %" PRId64, previously_encrypted_upto);
254687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
254787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
254887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (*size_already_done + size < previously_encrypted_upto) {
254987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        *size_already_done += size;
255087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        return 0;
255187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
255287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
2553e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    /* TODO: identify filesystem type.
2554e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg     * As is, cryptfs_enable_inplace_ext4 will fail on an f2fs partition, and
2555e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg     * then we will drop down to cryptfs_enable_inplace_f2fs.
2556e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg     * */
25577fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    if ((rc_ext4 = cryptfs_enable_inplace_ext4(crypto_blkdev, real_blkdev,
2558e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg                                size, size_already_done,
25597fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall                                tot_size, previously_encrypted_upto)) == 0) {
2560e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg      return 0;
2561e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg    }
25627fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    SLOGD("cryptfs_enable_inplace_ext4()=%d\n", rc_ext4);
2563e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
25647fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    if ((rc_f2fs = cryptfs_enable_inplace_f2fs(crypto_blkdev, real_blkdev,
2565e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg                                size, size_already_done,
25667fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall                                tot_size, previously_encrypted_upto)) == 0) {
2567e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg      return 0;
2568ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence    }
25697fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    SLOGD("cryptfs_enable_inplace_f2fs()=%d\n", rc_f2fs);
2570ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
25717fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    rc_full = cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev,
257287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                       size, size_already_done, tot_size,
257387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                       previously_encrypted_upto);
25747fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    SLOGD("cryptfs_enable_inplace_full()=%d\n", rc_full);
25757fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall
25767fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    /* Hack for b/17898962, the following is the symptom... */
25777fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    if (rc_ext4 == ENABLE_INPLACE_ERR_DEV
25787fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        && rc_f2fs == ENABLE_INPLACE_ERR_DEV
25797fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        && rc_full == ENABLE_INPLACE_ERR_DEV) {
25807fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall            return ENABLE_INPLACE_ERR_DEV;
25817fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    }
25827fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall    return rc_full;
2583ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence}
2584ae59fe6c1988af93c171e1b921a465c4fb1daabbPaul Lawrence
25858f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#define CRYPTO_ENABLE_WIPE 1
25868f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#define CRYPTO_ENABLE_INPLACE 2
25878ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
25888ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall#define FRAMEWORK_BOOT_WAIT 60
25898ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
259087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrencestatic int cryptfs_SHA256_fileblock(const char* filename, __le8* buf)
259187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence{
2592ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    int fd = open(filename, O_RDONLY|O_CLOEXEC);
259387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (fd == -1) {
259487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        SLOGE("Error opening file %s", filename);
259587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        return -1;
259687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
259787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
259887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    char block[CRYPT_INPLACE_BUFSIZE];
259987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    memset(block, 0, sizeof(block));
260087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (unix_read(fd, block, sizeof(block)) < 0) {
260187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        SLOGE("Error reading file %s", filename);
260287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        close(fd);
260387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        return -1;
260487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
260587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
260687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    close(fd);
260787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
260887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    SHA256_CTX c;
260987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    SHA256_Init(&c);
261087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    SHA256_Update(&c, block, sizeof(block));
261187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    SHA256_Final(buf, &c);
261287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
261387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    return 0;
261487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence}
261587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
261662c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrallstatic int get_fs_type(struct fstab_rec *rec)
261762c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall{
261862c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall    if (!strcmp(rec->fs_type, "ext4")) {
261962c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        return EXT4_FS;
262062c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall    } else if (!strcmp(rec->fs_type, "f2fs")) {
262162c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        return F2FS_FS;
262262c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall    } else {
262362c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        return -1;
262462c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall    }
262562c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall}
262662c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall
262787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrencestatic int cryptfs_enable_all_volumes(struct crypt_mnt_ftr *crypt_ftr, int how,
262887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                      char *crypto_blkdev, char *real_blkdev,
262987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                      int previously_encrypted_upto)
263087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence{
263187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    off64_t cur_encryption_done=0, tot_encryption_size=0;
26328439dc9fd569794b1a31f67cf43d9212de33eeccTim Murray    int rc = -1;
263387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
263473d7a02dc6e18b4c0a6f29e8f89b432c1b6cc808Paul Lawrence    if (!is_battery_ok_to_start()) {
263573d7a02dc6e18b4c0a6f29e8f89b432c1b6cc808Paul Lawrence        SLOGW("Not starting encryption due to low battery");
263687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        return 0;
263787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
263887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
263987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    /* The size of the userdata partition, and add in the vold volumes below */
264087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    tot_encryption_size = crypt_ftr->fs_size;
264187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
264287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (how == CRYPTO_ENABLE_WIPE) {
264362c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, DATA_MNT_POINT);
264462c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        int fs_type = get_fs_type(rec);
264562c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        if (fs_type < 0) {
264662c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall            SLOGE("cryptfs_enable: unsupported fs type %s\n", rec->fs_type);
264762c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall            return -1;
264862c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        }
264962c7af38f2f30b3f152460a8f716fe43e4acad7bJP Abgrall        rc = cryptfs_enable_wipe(crypto_blkdev, crypt_ftr->fs_size, fs_type);
265087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    } else if (how == CRYPTO_ENABLE_INPLACE) {
265187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        rc = cryptfs_enable_inplace(crypto_blkdev, real_blkdev,
265287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                    crypt_ftr->fs_size, &cur_encryption_done,
265387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                    tot_encryption_size,
265487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                    previously_encrypted_upto);
265587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
26567fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        if (rc == ENABLE_INPLACE_ERR_DEV) {
26577fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall            /* Hack for b/17898962 */
26587fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall            SLOGE("cryptfs_enable: crypto block dev failure. Must reboot...\n");
26597fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall            cryptfs_reboot(reboot);
26607fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall        }
26617fc1de8a44307d6c51826ab90f804702e08d1e6dJP Abgrall
266273d7a02dc6e18b4c0a6f29e8f89b432c1b6cc808Paul Lawrence        if (!rc) {
266387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            crypt_ftr->encrypted_upto = cur_encryption_done;
266487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
266587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
266673d7a02dc6e18b4c0a6f29e8f89b432c1b6cc808Paul Lawrence        if (!rc && crypt_ftr->encrypted_upto == crypt_ftr->fs_size) {
266787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            /* The inplace routine never actually sets the progress to 100% due
266887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence             * to the round down nature of integer division, so set it here */
266987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            property_set("vold.encrypt_progress", "100");
267087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
267187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    } else {
267287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        /* Shouldn't happen */
267387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        SLOGE("cryptfs_enable: internal error, unknown option\n");
267487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        rc = -1;
267587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
267687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
267787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    return rc;
267887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence}
267987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
26804375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wangint cryptfs_enable_internal(char *howarg, int crypt_type, const char *passwd,
2681569649ff1d6d76f89982c391a5b0e119050250e4Paul Lawrence                            int no_ui)
26828f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall{
26838f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    int how = 0;
268487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    char crypto_blkdev[MAXPATHLEN], real_blkdev[MAXPATHLEN];
2685160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    unsigned char decrypted_master_key[KEY_LEN_BYTES];
268614eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    int rc=-1, i;
268787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    struct crypt_mnt_ftr crypt_ftr;
2688160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    struct crypt_persist_data *pdata;
268929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    char encrypted_state[PROPERTY_VALUE_MAX];
26905d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall    char lockid[32] = { 0 };
269129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    char key_loc[PROPERTY_VALUE_MAX];
269229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    int num_vols;
269387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    off64_t previously_encrypted_upto = 0;
26943d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    bool rebootEncryption = false;
26954375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    bool onlyCreateHeader = false;
26964375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    int fd = -1;
269729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
26988f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    if (!strcmp(howarg, "wipe")) {
26998f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall      how = CRYPTO_ENABLE_WIPE;
27008f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    } else if (! strcmp(howarg, "inplace")) {
27018f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall      how = CRYPTO_ENABLE_INPLACE;
27028f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    } else {
27038f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall      /* Shouldn't happen, as CommandListener vets the args */
27043ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall      goto error_unencrypted;
27058f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
27068f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
270787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (how == CRYPTO_ENABLE_INPLACE
27083d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence          && get_crypt_ftr_and_key(&crypt_ftr) == 0) {
27093d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        if (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS) {
27103d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            /* An encryption was underway and was interrupted */
27113d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            previously_encrypted_upto = crypt_ftr.encrypted_upto;
27123d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            crypt_ftr.encrypted_upto = 0;
27133d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            crypt_ftr.flags &= ~CRYPT_ENCRYPTION_IN_PROGRESS;
27143d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
27153d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            /* At this point, we are in an inconsistent state. Until we successfully
27163d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence               complete encryption, a reboot will leave us broken. So mark the
27173d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence               encryption failed in case that happens.
27183d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence               On successfully completing encryption, remove this flag */
27193d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE;
27203d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
27213d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            put_crypt_ftr_and_key(&crypt_ftr);
27223d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        } else if (crypt_ftr.flags & CRYPT_FORCE_ENCRYPTION) {
27233d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            if (!check_ftr_sha(&crypt_ftr)) {
27243d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                memset(&crypt_ftr, 0, sizeof(crypt_ftr));
27253d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                put_crypt_ftr_and_key(&crypt_ftr);
27263d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                goto error_unencrypted;
27273d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            }
27286bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence
27293d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            /* Doing a reboot-encryption*/
27303d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            crypt_ftr.flags &= ~CRYPT_FORCE_ENCRYPTION;
27313d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            crypt_ftr.flags |= CRYPT_FORCE_COMPLETE;
27323d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            rebootEncryption = true;
27333d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        }
273487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
273587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
273687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    property_get("ro.crypto.state", encrypted_state, "");
273787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (!strcmp(encrypted_state, "encrypted") && !previously_encrypted_upto) {
273887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        SLOGE("Device is already running encrypted, aborting");
273987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        goto error_unencrypted;
274087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
274187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
274287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    // TODO refactor fs_mgr_get_crypt_info to get both in one call
274387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    fs_mgr_get_crypt_info(fstab, key_loc, 0, sizeof(key_loc));
274456ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
27458f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
27463ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    /* Get the size of the real block device */
27474375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang    fd = open(real_blkdev, O_RDONLY|O_CLOEXEC);
274814eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    if (fd == -1) {
274914eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa        SLOGE("Cannot open block device %s\n", real_blkdev);
275014eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa        goto error_unencrypted;
275114eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    }
275214eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    unsigned long nr_sec;
275314eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    get_blkdev_size(fd, &nr_sec);
275414eab550e8a4f28889cc9ffbb92ddff8f18c4f03Hiroaki Miyazawa    if (nr_sec == 0) {
27553ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        SLOGE("Cannot get size of block device %s\n", real_blkdev);
27563ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        goto error_unencrypted;
27573ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    }
27583ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    close(fd);
27593ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
27603ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    /* If doing inplace encryption, make sure the orig fs doesn't include the crypto footer */
276129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    if ((how == CRYPTO_ENABLE_INPLACE) && (!strcmp(key_loc, KEY_IN_FOOTER))) {
27623ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        unsigned int fs_size_sec, max_fs_size_sec;
2763a70abc60091aed3c3eaf8bc8e1766e233c1c3a2fJim Miller        fs_size_sec = get_fs_size(real_blkdev);
2764e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg        if (fs_size_sec == 0)
2765e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg            fs_size_sec = get_f2fs_filesystem_size_sec(real_blkdev);
2766e82df164e8128ec9df0072c4a4f3d92e79a0f5f4Daniel Rosenberg
276787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        max_fs_size_sec = nr_sec - (CRYPT_FOOTER_OFFSET / CRYPT_SECTOR_SIZE);
27683ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
27693ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        if (fs_size_sec > max_fs_size_sec) {
27703ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall            SLOGE("Orig filesystem overlaps crypto footer region.  Cannot encrypt in place.");
27713ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall            goto error_unencrypted;
27723ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        }
27733ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    }
27743ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
27755d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall    /* Get a wakelock as this may take a while, and we don't want the
27765d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall     * device to sleep on us.  We'll grab a partial wakelock, and if the UI
27775d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall     * wants to keep the screen on, it can grab a full wakelock.
27785d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall     */
277929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    snprintf(lockid, sizeof(lockid), "enablecrypto%d", (int) getpid());
27805d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall    acquire_wake_lock(PARTIAL_WAKE_LOCK, lockid);
27815d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall
27828f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    /* The init files are setup to stop the class main and late start when
27838ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall     * vold sets trigger_shutdown_framework.
27848f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall     */
27858f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    property_set("vold.decrypt", "trigger_shutdown_framework");
27868f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    SLOGD("Just asked init to shut down class main\n");
27878f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
27889c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    /* Ask vold to unmount all devices that it manages */
27899c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    if (vold_unmountAll()) {
27909c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        SLOGE("Failed to unmount all vold managed devices");
27912eaf7138528d30c331d83ab8346a97e66b5499e2Ken Sumrall    }
27928f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
27933d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    /* no_ui means we are being called from init, not settings.
27943d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence       Now we always reboot from settings, so !no_ui means reboot
27953d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence     */
27963d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (!no_ui) {
27973d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        /* Try fallback, which is to reboot and try there */
27983d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        onlyCreateHeader = true;
27993d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        FILE* breadcrumb = fopen(BREADCRUMB_FILE, "we");
28003d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        if (breadcrumb == 0) {
28013d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            SLOGE("Failed to create breadcrumb file");
28023d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            goto error_shutting_down;
28033d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        }
28043d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        fclose(breadcrumb);
28058ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    }
28068f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
28078ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    /* Do extra work for a better UX when doing the long inplace encryption */
28083d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (how == CRYPTO_ENABLE_INPLACE && !onlyCreateHeader) {
28098ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        /* Now that /data is unmounted, we need to mount a tmpfs
28108ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall         * /data, set a property saying we're doing inplace encryption,
28118ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall         * and restart the framework.
28128ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall         */
2813e5032c42da3c33a854df0a24a7968b4ab54190b9Ken Sumrall        if (fs_mgr_do_tmpfs_mount(DATA_MNT_POINT)) {
28143ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall            goto error_shutting_down;
28158f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        }
28168ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        /* Tells the framework that inplace encryption is starting */
28177df84120b25dca713f623528801385b00208c2aaKen Sumrall        property_set("vold.encrypt_progress", "0");
28188f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
28198ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        /* restart the framework. */
28208ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        /* Create necessary paths on /data */
28218ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        if (prep_data_fs()) {
28223ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall            goto error_shutting_down;
28238f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        }
28248f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
282592736efab068bdbfeb1177544907b84511fb04e0Ken Sumrall        /* Ugh, shutting down the framework is not synchronous, so until it
282692736efab068bdbfeb1177544907b84511fb04e0Ken Sumrall         * can be fixed, this horrible hack will wait a moment for it all to
282792736efab068bdbfeb1177544907b84511fb04e0Ken Sumrall         * shut down before proceeding.  Without it, some devices cannot
282892736efab068bdbfeb1177544907b84511fb04e0Ken Sumrall         * restart the graphics services.
282992736efab068bdbfeb1177544907b84511fb04e0Ken Sumrall         */
283092736efab068bdbfeb1177544907b84511fb04e0Ken Sumrall        sleep(2);
28318ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    }
28328f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
28338ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    /* Start the actual work of making an encrypted filesystem */
28348ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    /* Initialize a crypt_mnt_ftr for the partition */
28353d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (previously_encrypted_upto == 0 && !rebootEncryption) {
283669f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        if (cryptfs_init_crypt_mnt_ftr(&crypt_ftr)) {
283769f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence            goto error_shutting_down;
283869f4ebd81e22f91a4571763842b5960d95d2758dPaul Lawrence        }
2839160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
284087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        if (!strcmp(key_loc, KEY_IN_FOOTER)) {
284187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            crypt_ftr.fs_size = nr_sec
284287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence              - (CRYPT_FOOTER_OFFSET / CRYPT_SECTOR_SIZE);
284387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        } else {
284487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            crypt_ftr.fs_size = nr_sec;
284587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
28466bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence        /* At this point, we are in an inconsistent state. Until we successfully
28476bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence           complete encryption, a reboot will leave us broken. So mark the
28486bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence           encryption failed in case that happens.
28496bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence           On successfully completing encryption, remove this flag */
28503d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        if (onlyCreateHeader) {
28513d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            crypt_ftr.flags |= CRYPT_FORCE_ENCRYPTION;
28523d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        } else {
28533d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE;
28543d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        }
285587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        crypt_ftr.crypt_type = crypt_type;
285687701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani        strlcpy((char *)crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256", MAX_CRYPTO_TYPE_NAME_LEN);
28578ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
285887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        /* Make an encrypted master key */
28593d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        if (create_encrypted_random_key(onlyCreateHeader ? DEFAULT_PASSWORD : passwd,
28603d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                                        crypt_ftr.master_key, crypt_ftr.salt, &crypt_ftr)) {
286187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Cannot create encrypted master key\n");
286287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            goto error_shutting_down;
286387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
28648ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
28653d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        /* Replace scrypted intermediate key if we are preparing for a reboot */
28663d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        if (onlyCreateHeader) {
28673d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            unsigned char fake_master_key[KEY_LEN_BYTES];
28683d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            unsigned char encrypted_fake_master_key[KEY_LEN_BYTES];
28693d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            memset(fake_master_key, 0, sizeof(fake_master_key));
28703d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            encrypt_master_key(passwd, crypt_ftr.salt, fake_master_key,
28713d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                               encrypted_fake_master_key, &crypt_ftr);
28723d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        }
28733d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
287487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        /* Write the key to the end of the partition */
287587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        put_crypt_ftr_and_key(&crypt_ftr);
28768ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
287787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        /* If any persistent data has been remembered, save it.
287887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence         * If none, create a valid empty table and save that.
287987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence         */
288087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        if (!persist_data) {
28814375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang            pdata = (crypt_persist_data *)malloc(CRYPT_PERSIST_DATA_SIZE);
288287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence           if (pdata) {
288387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence               init_empty_persist_data(pdata, CRYPT_PERSIST_DATA_SIZE);
288487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence               persist_data = pdata;
288587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence           }
288687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
288787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        if (persist_data) {
288887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            save_persistent_data();
288987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
2890160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
2891160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
28923d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (onlyCreateHeader) {
28933d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        sleep(2);
28943d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence        cryptfs_reboot(reboot);
28953d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    }
28963d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence
28973d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    if (how == CRYPTO_ENABLE_INPLACE && (!no_ui || rebootEncryption)) {
289887701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani        /* startup service classes main and late_start */
289987701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani        property_set("vold.decrypt", "trigger_restart_min_framework");
290087701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani        SLOGD("Just triggered restart_min_framework\n");
290187701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani
290287701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani        /* OK, the framework is restarted and will soon be showing a
290387701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani         * progress bar.  Time to setup an encrypted mapping, and
290487701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani         * either write a new filesystem, or encrypt in place updating
290587701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani         * the progress bar as we work.
290687701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani         */
290787701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani    }
290887701e2755f039d6ea8c1510dcddf468ee947a62Ajay Dudani
2909d0c7b17070d4321fef096873b4890794024a5f63Paul Lawrence    decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
291029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev,
29113d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                          CRYPTO_BLOCK_DEVICE);
291229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
291387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    /* If we are continuing, check checksums match */
291487999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    rc = 0;
291587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (previously_encrypted_upto) {
291687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        __le8 hash_first_block[SHA256_DIGEST_LENGTH];
291787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        rc = cryptfs_SHA256_fileblock(crypto_blkdev, hash_first_block);
291887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
291987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        if (!rc && memcmp(hash_first_block, crypt_ftr.hash_first_block,
292087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                          sizeof(hash_first_block)) != 0) {
292187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Checksums do not match - trigger wipe");
292287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            rc = -1;
292329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        }
292429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
29258ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
292687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    if (!rc) {
292787999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        rc = cryptfs_enable_all_volumes(&crypt_ftr, how,
292887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                        crypto_blkdev, real_blkdev,
292987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                        previously_encrypted_upto);
293087999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    }
293187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence
293287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    /* Calculate checksum if we are not finished */
2933b1eb7a06ee24078efb3a7efaa32c1561b92f4cb8Paul Lawrence    if (!rc && how == CRYPTO_ENABLE_INPLACE
2934b1eb7a06ee24078efb3a7efaa32c1561b92f4cb8Paul Lawrence            && crypt_ftr.encrypted_upto != crypt_ftr.fs_size) {
293587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        rc = cryptfs_SHA256_fileblock(crypto_blkdev,
293687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                                      crypt_ftr.hash_first_block);
293773d7a02dc6e18b4c0a6f29e8f89b432c1b6cc808Paul Lawrence        if (rc) {
293887999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGE("Error calculating checksum for continuing encryption");
293987999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            rc = -1;
294029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        }
29418ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    }
29428ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
29438ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    /* Undo the dm-crypt mapping whether we succeed or not */
29443d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence    delete_crypto_blk_dev(CRYPTO_BLOCK_DEVICE);
294529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
29468ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    if (! rc) {
29478ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        /* Success */
29486bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence        crypt_ftr.flags &= ~CRYPT_INCONSISTENT_STATE;
29497f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall
2950b1eb7a06ee24078efb3a7efaa32c1561b92f4cb8Paul Lawrence        if (how == CRYPTO_ENABLE_INPLACE
2951b1eb7a06ee24078efb3a7efaa32c1561b92f4cb8Paul Lawrence              && crypt_ftr.encrypted_upto != crypt_ftr.fs_size) {
295287999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            SLOGD("Encrypted up to sector %lld - will continue after reboot",
295387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence                  crypt_ftr.encrypted_upto);
29546bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence            crypt_ftr.flags |= CRYPT_ENCRYPTION_IN_PROGRESS;
295587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
295673d7a02dc6e18b4c0a6f29e8f89b432c1b6cc808Paul Lawrence
29576bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence        put_crypt_ftr_and_key(&crypt_ftr);
2958d33d417e3a057fffad22c23f5f002177531db2a5Ken Sumrall
2959b1eb7a06ee24078efb3a7efaa32c1561b92f4cb8Paul Lawrence        if (how == CRYPTO_ENABLE_WIPE
2960b1eb7a06ee24078efb3a7efaa32c1561b92f4cb8Paul Lawrence              || crypt_ftr.encrypted_upto == crypt_ftr.fs_size) {
2961b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence          char value[PROPERTY_VALUE_MAX];
2962b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence          property_get("ro.crypto.state", value, "");
2963b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence          if (!strcmp(value, "")) {
2964b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence            /* default encryption - continue first boot sequence */
2965b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence            property_set("ro.crypto.state", "encrypted");
29664ed4526e68b10c9d583541da9dadaf3d29b769cdPaul Lawrence            property_set("ro.crypto.type", "block");
2967b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence            release_wake_lock(lockid);
29683d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            if (rebootEncryption && crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) {
29693d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                // Bring up cryptkeeper that will check the password and set it
29703d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                property_set("vold.decrypt", "trigger_shutdown_framework");
29713d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                sleep(2);
29723d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                property_set("vold.encrypt_progress", "");
29733d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                cryptfs_trigger_restart_min_framework();
29743d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            } else {
29753d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                cryptfs_check_passwd(DEFAULT_PASSWORD);
29763d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence                cryptfs_restart_internal(1);
29773d99ebad3ddcd7e4a30bca82ba8bd641c3a71038Paul Lawrence            }
2978b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence            return 0;
2979b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence          } else {
2980b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence            sleep(2); /* Give the UI a chance to show 100% progress */
298187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            cryptfs_reboot(reboot);
2982b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence          }
298387999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        } else {
2984b6672e135ac7a5a1d5b1d277cf678096c57dd7ddPaul Lawrence            sleep(2); /* Partially encrypted, ensure writes flushed to ssd */
298587999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            cryptfs_reboot(shutdown);
298687999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence        }
29873ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    } else {
2988ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood        char value[PROPERTY_VALUE_MAX];
2989ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood
2990319369ac111aec79b42668477c998c36b5f3be06Ken Sumrall        property_get("ro.vold.wipe_on_crypt_fail", value, "0");
2991ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood        if (!strcmp(value, "1")) {
2992ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood            /* wipe data if encryption failed */
2993ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood            SLOGE("encryption failed - rebooting into recovery to wipe data\n");
29944375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang            std::string err;
29954375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang            const std::vector<std::string> options = {
29964375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang                "--wipe_data\n--reason=cryptfs_enable_internal\n"
29974375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang            };
29984375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang            if (!write_bootloader_message(options, &err)) {
29994375f1be4ccdbf78ef4c5ab926d3316503a7b146Wei Wang                SLOGE("could not write bootloader message: %s", err.c_str());
3000ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood            }
300187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence            cryptfs_reboot(recovery);
3002ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood        } else {
3003ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood            /* set property to trigger dialog */
3004ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood            property_set("vold.encrypt_progress", "error_partially_encrypted");
3005ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood            release_wake_lock(lockid);
3006ee6d8c42f337ea1446a319df53f6d1a96afbd209Mike Lockwood        }
30073ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall        return -1;
30088ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    }
30098ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
30103ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    /* hrm, the encrypt step claims success, but the reboot failed.
30113ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall     * This should not happen.
30123ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall     * Set the property and return.  Hope the framework can deal with it.
30133ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall     */
30143ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    property_set("vold.encrypt_progress", "error_reboot_failed");
30155d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall    release_wake_lock(lockid);
30168ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    return rc;
30173ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
30183ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrallerror_unencrypted:
30193ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    property_set("vold.encrypt_progress", "error_not_encrypted");
30205d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall    if (lockid[0]) {
30215d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall        release_wake_lock(lockid);
30225d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall    }
30233ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    return -1;
30243ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
30253ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrallerror_shutting_down:
30263ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    /* we failed, and have not encrypted anthing, so the users's data is still intact,
30273ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall     * but the framework is stopped and not restarted to show the error, so it's up to
30283ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall     * vold to restart the system.
30293ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall     */
30303ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    SLOGE("Error enabling encryption after framework is shutdown, no data changed, restarting system");
303187999173dd79dbcbd8cb97f5476007e867aaeebaPaul Lawrence    cryptfs_reboot(reboot);
30323ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall
30333ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    /* shouldn't get here */
30343ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    property_set("vold.encrypt_progress", "error_shutting_down");
30355d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall    if (lockid[0]) {
30365d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall        release_wake_lock(lockid);
30375d4c68e40700424b65a4331be75620706a0dd49cKen Sumrall    }
30383ed8236de11a1be8b45d4c37b2208682f5e97c72Ken Sumrall    return -1;
30398ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall}
30408ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
3041569649ff1d6d76f89982c391a5b0e119050250e4Paul Lawrenceint cryptfs_enable(char *howarg, int type, char *passwd, int no_ui)
304213486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence{
3043569649ff1d6d76f89982c391a5b0e119050250e4Paul Lawrence    return cryptfs_enable_internal(howarg, type, passwd, no_ui);
304413486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence}
304513486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence
3046569649ff1d6d76f89982c391a5b0e119050250e4Paul Lawrenceint cryptfs_enable_default(char *howarg, int no_ui)
304713486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence{
304813486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence    return cryptfs_enable_internal(howarg, CRYPT_TYPE_DEFAULT,
3049569649ff1d6d76f89982c391a5b0e119050250e4Paul Lawrence                          DEFAULT_PASSWORD, no_ui);
305013486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence}
305113486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence
305213486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrenceint cryptfs_changepw(int crypt_type, const char *newpw)
30538ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall{
305438132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (e4crypt_is_native()) {
30557b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        SLOGE("cryptfs_changepw not valid for file encryption");
30567b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        return -1;
305705335c344d73411439774dfa548c633020e158e1Paul Lawrence    }
305805335c344d73411439774dfa548c633020e158e1Paul Lawrence
30598ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    struct crypt_mnt_ftr crypt_ftr;
3060933216c8861b6b3f0e65cd27812ce2e3c26721c4JP Abgrall    int rc;
30618ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
30628ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    /* This is only allowed after we've successfully decrypted the master key */
3063f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    if (!master_key_saved) {
30640cc166385a7e1d3026bbcb62f094e419f779e872Ken Sumrall        SLOGE("Key not saved, aborting");
30658ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        return -1;
30668ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    }
30678ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
3068f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) {
3069f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGE("Invalid crypt_type %d", crypt_type);
3070f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        return -1;
3071f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    }
3072f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
30738ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    /* get key */
3074160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (get_crypt_ftr_and_key(&crypt_ftr)) {
3075f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGE("Error getting crypt footer and key");
3076f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        return -1;
30778ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    }
30788ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall
3079f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    crypt_ftr.crypt_type = crypt_type;
3080f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
3081933216c8861b6b3f0e65cd27812ce2e3c26721c4JP Abgrall    rc = encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD
3082f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                                                        : newpw,
3083f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                       crypt_ftr.salt,
3084f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                       saved_master_key,
3085f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                       crypt_ftr.master_key,
3086f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                       &crypt_ftr);
3087933216c8861b6b3f0e65cd27812ce2e3c26721c4JP Abgrall    if (rc) {
3088933216c8861b6b3f0e65cd27812ce2e3c26721c4JP Abgrall        SLOGE("Encrypt master key failed: %d", rc);
3089933216c8861b6b3f0e65cd27812ce2e3c26721c4JP Abgrall        return -1;
3090933216c8861b6b3f0e65cd27812ce2e3c26721c4JP Abgrall    }
309170a4b3fd7a84a84bbe6e9d6d4ca3ee2098259fd9Jason parks    /* save the key */
3092160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    put_crypt_ftr_and_key(&crypt_ftr);
30938f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
30948f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return 0;
30958f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
3096160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
309785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xustatic unsigned int persist_get_max_entries(int encrypted) {
309885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    struct crypt_mnt_ftr crypt_ftr;
309985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int dsize;
310085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int max_persistent_entries;
310185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
310285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    /* If encrypted, use the values from the crypt_ftr, otherwise
310385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu     * use the values for the current spec.
310485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu     */
310585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (encrypted) {
310685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        if (get_crypt_ftr_and_key(&crypt_ftr)) {
310785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            return -1;
310885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        }
310985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        dsize = crypt_ftr.persist_data_size;
311085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    } else {
311185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        dsize = CRYPT_PERSIST_DATA_SIZE;
311285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
311385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
311485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    max_persistent_entries = (dsize - sizeof(struct crypt_persist_data)) /
311585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        sizeof(struct crypt_persist_entry);
311685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
311785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    return max_persistent_entries;
311885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu}
311985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
312085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xustatic int persist_get_key(const char *fieldname, char *value)
3121160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
3122160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    unsigned int i;
3123160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3124160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (persist_data == NULL) {
3125160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
3126160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3127160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    for (i = 0; i < persist_data->persist_valid_entries; i++) {
3128160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (!strncmp(persist_data->persist_entry[i].key, fieldname, PROPERTY_KEY_MAX)) {
3129160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            /* We found it! */
3130160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            strlcpy(value, persist_data->persist_entry[i].val, PROPERTY_VALUE_MAX);
3131160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            return 0;
3132160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
3133160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3134160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3135160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
3136160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
3137160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
313885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xustatic int persist_set_key(const char *fieldname, const char *value, int encrypted)
3139160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
3140160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    unsigned int i;
3141160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    unsigned int num;
3142160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    unsigned int max_persistent_entries;
3143160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3144160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (persist_data == NULL) {
3145160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return -1;
3146160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3147160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
314885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    max_persistent_entries = persist_get_max_entries(encrypted);
3149160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3150160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    num = persist_data->persist_valid_entries;
3151160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3152160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    for (i = 0; i < num; i++) {
3153160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (!strncmp(persist_data->persist_entry[i].key, fieldname, PROPERTY_KEY_MAX)) {
3154160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            /* We found an existing entry, update it! */
3155160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            memset(persist_data->persist_entry[i].val, 0, PROPERTY_VALUE_MAX);
3156160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            strlcpy(persist_data->persist_entry[i].val, value, PROPERTY_VALUE_MAX);
3157160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            return 0;
3158160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
3159160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3160160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3161160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    /* We didn't find it, add it to the end, if there is room */
3162160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (persist_data->persist_valid_entries < max_persistent_entries) {
3163160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        memset(&persist_data->persist_entry[num], 0, sizeof(struct crypt_persist_entry));
3164160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        strlcpy(persist_data->persist_entry[num].key, fieldname, PROPERTY_KEY_MAX);
3165160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        strlcpy(persist_data->persist_entry[num].val, value, PROPERTY_VALUE_MAX);
3166160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        persist_data->persist_valid_entries++;
3167160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        return 0;
3168160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3169160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3170160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return -1;
3171160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
3172160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
317385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu/**
317485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu * Test if key is part of the multi-entry (field, index) sequence. Return non-zero if key is in the
317585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu * sequence and its index is greater than or equal to index. Return 0 otherwise.
317685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu */
317785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xustatic int match_multi_entry(const char *key, const char *field, unsigned index) {
317885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int field_len;
317985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int key_index;
318085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    field_len = strlen(field);
318185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
318285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (index == 0) {
318385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // The first key in a multi-entry field is just the filedname itself.
318485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        if (!strcmp(key, field)) {
318585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            return 1;
318685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        }
318785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
318885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    // Match key against "%s_%d" % (field, index)
318985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (strlen(key) < field_len + 1 + 1) {
319085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // Need at least a '_' and a digit.
319185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        return 0;
319285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
319385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (strncmp(key, field, field_len)) {
319485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // If the key does not begin with field, it's not a match.
319585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        return 0;
319685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
319785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (1 != sscanf(&key[field_len],"_%d", &key_index)) {
319885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        return 0;
319985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
320085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    return key_index >= index;
320185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu}
320285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
320385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu/*
320485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu * Delete entry/entries from persist_data. If the entries are part of a multi-segment field, all
320585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu * remaining entries starting from index will be deleted.
320685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu * returns PERSIST_DEL_KEY_OK if deletion succeeds,
320785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu * PERSIST_DEL_KEY_ERROR_NO_FIELD if the field does not exist,
320885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu * and PERSIST_DEL_KEY_ERROR_OTHER if error occurs.
320985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu *
321085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu */
321185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xustatic int persist_del_keys(const char *fieldname, unsigned index)
321285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu{
321385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int i;
321485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int j;
321585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int num;
321685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
321785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (persist_data == NULL) {
321885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        return PERSIST_DEL_KEY_ERROR_OTHER;
321985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
322085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
322185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    num = persist_data->persist_valid_entries;
322285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
322385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    j = 0; // points to the end of non-deleted entries.
322485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    // Filter out to-be-deleted entries in place.
322585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    for (i = 0; i < num; i++) {
322685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        if (!match_multi_entry(persist_data->persist_entry[i].key, fieldname, index)) {
322785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            persist_data->persist_entry[j] = persist_data->persist_entry[i];
322885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            j++;
322985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        }
323085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
323185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
323285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (j < num) {
323385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        persist_data->persist_valid_entries = j;
323485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // Zeroise the remaining entries
323585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        memset(&persist_data->persist_entry[j], 0, (num - j) * sizeof(struct crypt_persist_entry));
323685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        return PERSIST_DEL_KEY_OK;
323785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    } else {
323885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // Did not find an entry matching the given fieldname
323985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        return PERSIST_DEL_KEY_ERROR_NO_FIELD;
324085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
324185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu}
324285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
324385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xustatic int persist_count_keys(const char *fieldname)
324485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu{
324585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int i;
324685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int count;
324785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
324885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (persist_data == NULL) {
324985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        return -1;
325085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
325185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
325285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    count = 0;
325385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    for (i = 0; i < persist_data->persist_valid_entries; i++) {
325485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        if (match_multi_entry(persist_data->persist_entry[i].key, fieldname, 0)) {
325585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            count++;
325685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        }
325785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
325885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
325985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    return count;
326085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu}
326185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
3262160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall/* Return the value of the specified field. */
326385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xuint cryptfs_getfield(const char *fieldname, char *value, int len)
3264160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
326538132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (e4crypt_is_native()) {
32665a06a6481bff8916bf366bf9e951ab5c6a405207Paul Lawrence        SLOGE("Cannot get field when file encrypted");
32675a06a6481bff8916bf366bf9e951ab5c6a405207Paul Lawrence        return -1;
3268368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    }
3269368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence
3270160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    char temp_value[PROPERTY_VALUE_MAX];
327185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    /* CRYPTO_GETFIELD_OK is success,
327285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu     * CRYPTO_GETFIELD_ERROR_NO_FIELD is value not set,
327385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu     * CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL is buffer (as given by len) too small,
327485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu     * CRYPTO_GETFIELD_ERROR_OTHER is any other error
3275160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall     */
327685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    int rc = CRYPTO_GETFIELD_ERROR_OTHER;
327785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    int i;
327885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    char temp_field[PROPERTY_KEY_MAX];
3279160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3280160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (persist_data == NULL) {
3281160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        load_persistent_data();
3282160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (persist_data == NULL) {
3283160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            SLOGE("Getfield error, cannot load persistent data");
3284160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            goto out;
3285160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
3286160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3287160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
328885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    // Read value from persistent entries. If the original value is split into multiple entries,
328985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    // stitch them back together.
3290160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (!persist_get_key(fieldname, temp_value)) {
329185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // We found it, copy it to the caller's buffer and keep going until all entries are read.
329285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        if (strlcpy(value, temp_value, len) >= (unsigned) len) {
329385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            // value too small
329485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            rc = CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
329585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            goto out;
329685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        }
329785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        rc = CRYPTO_GETFIELD_OK;
329885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
329985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        for (i = 1; /* break explicitly */; i++) {
330085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            if (snprintf(temp_field, sizeof(temp_field), "%s_%d", fieldname, i) >=
330185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                    (int) sizeof(temp_field)) {
330285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                // If the fieldname is very long, we stop as soon as it begins to overflow the
330385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                // maximum field length. At this point we have in fact fully read out the original
330485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                // value because cryptfs_setfield would not allow fields with longer names to be
330585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                // written in the first place.
330685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                break;
330785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            }
330885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            if (!persist_get_key(temp_field, temp_value)) {
330985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                  if (strlcat(value, temp_value, len) >= (unsigned)len) {
331085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                      // value too small.
331185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                      rc = CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
331285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                      goto out;
331385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                  }
331485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            } else {
331585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                // Exhaust all entries.
331685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                break;
331785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            }
331885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        }
3319160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    } else {
3320160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        /* Sadness, it's not there.  Return the error */
332185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        rc = CRYPTO_GETFIELD_ERROR_NO_FIELD;
3322160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3323160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3324160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallout:
3325160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return rc;
3326160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
3327160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3328160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall/* Set the value of the specified field. */
332985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xuint cryptfs_setfield(const char *fieldname, const char *value)
3330160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall{
333138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (e4crypt_is_native()) {
33325a06a6481bff8916bf366bf9e951ab5c6a405207Paul Lawrence        SLOGE("Cannot set field when file encrypted");
33335a06a6481bff8916bf366bf9e951ab5c6a405207Paul Lawrence        return -1;
3334368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence    }
3335368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence
3336160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    char encrypted_state[PROPERTY_VALUE_MAX];
333785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    /* 0 is success, negative values are error */
333885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    int rc = CRYPTO_SETFIELD_ERROR_OTHER;
3339160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    int encrypted = 0;
334085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int field_id;
334185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    char temp_field[PROPERTY_KEY_MAX];
334285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int num_entries;
334385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    unsigned int max_keylen;
3344160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3345160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (persist_data == NULL) {
3346160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        load_persistent_data();
3347160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (persist_data == NULL) {
3348160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            SLOGE("Setfield error, cannot load persistent data");
3349160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            goto out;
3350160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
3351160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3352160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3353160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    property_get("ro.crypto.state", encrypted_state, "");
3354160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (!strcmp(encrypted_state, "encrypted") ) {
3355160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        encrypted = 1;
3356160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3357160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
335885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    // Compute the number of entries required to store value, each entry can store up to
335985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    // (PROPERTY_VALUE_MAX - 1) chars
336085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (strlen(value) == 0) {
336185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // Empty value also needs one entry to store.
336285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        num_entries = 1;
336385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    } else {
336485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        num_entries = (strlen(value) + (PROPERTY_VALUE_MAX - 1) - 1) / (PROPERTY_VALUE_MAX - 1);
336585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
336685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
336785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    max_keylen = strlen(fieldname);
336885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (num_entries > 1) {
336985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // Need an extra "_%d" suffix.
337085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        max_keylen += 1 + log10(num_entries);
337185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
337285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (max_keylen > PROPERTY_KEY_MAX - 1) {
337385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        rc = CRYPTO_SETFIELD_ERROR_FIELD_TOO_LONG;
337485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        goto out;
337585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
337685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
337785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    // Make sure we have enough space to write the new value
337885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    if (persist_data->persist_valid_entries + num_entries - persist_count_keys(fieldname) >
337985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        persist_get_max_entries(encrypted)) {
338085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        rc = CRYPTO_SETFIELD_ERROR_VALUE_TOO_LONG;
338185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        goto out;
338285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
338385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
338485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    // Now that we know persist_data has enough space for value, let's delete the old field first
338585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    // to make up space.
338685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    persist_del_keys(fieldname, 0);
338785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
3388160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (persist_set_key(fieldname, value, encrypted)) {
338985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // fail to set key, should not happen as we have already checked the available space
339085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        SLOGE("persist_set_key() error during setfield()");
3391160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        goto out;
3392160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3393160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
339485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    for (field_id = 1; field_id < num_entries; field_id++) {
339585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        snprintf(temp_field, sizeof(temp_field), "%s_%d", fieldname, field_id);
339685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
339785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        if (persist_set_key(temp_field, value + field_id * (PROPERTY_VALUE_MAX - 1), encrypted)) {
339885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            // fail to set key, should not happen as we have already checked the available space.
339985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            SLOGE("persist_set_key() error during setfield()");
340085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            goto out;
340185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        }
340285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    }
340385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
3404160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    /* If we are running encrypted, save the persistent data now */
3405160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    if (encrypted) {
3406160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (save_persistent_data()) {
3407160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            SLOGE("Setfield error, cannot save persistent data");
3408160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            goto out;
3409160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
3410160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    }
3411160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
341285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu    rc = CRYPTO_SETFIELD_OK;
3413160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
3414160b4d68ece15947057e31edde4e5608a010c695Ken Sumrallout:
3415160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    return rc;
3416160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall}
3417f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
3418f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence/* Checks userdata. Attempt to mount the volume if default-
3419f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence * encrypted.
3420f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence * On success trigger next init phase and return 0.
3421f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence * Currently do not handle failure - see TODO below.
3422f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence */
3423f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrenceint cryptfs_mount_default_encrypted(void)
3424f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence{
342584274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence    int crypt_type = cryptfs_get_password_type();
342684274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence    if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) {
342784274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence        SLOGE("Bad crypt type - error");
342884274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence    } else if (crypt_type != CRYPT_TYPE_DEFAULT) {
342984274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence        SLOGD("Password is not default - "
343084274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence              "starting min framework to prompt");
343184274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence        property_set("vold.decrypt", "trigger_restart_min_framework");
343284274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence        return 0;
343384274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence    } else if (cryptfs_check_passwd(DEFAULT_PASSWORD) == 0) {
343484274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence        SLOGD("Password is default - restarting filesystem");
343584274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence        cryptfs_restart_internal(0);
343684274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence        return 0;
3437f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    } else {
343884274cc35cf4100794796e2027e733fa2fc8cd1fPaul Lawrence        SLOGE("Encrypted, default crypt type but can't decrypt");
3439f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    }
3440f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
34416bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence    /** Corrupt. Allow us to boot into framework, which will detect bad
34426bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence        crypto when it calls do_crypto_complete, then do a factory reset
3443f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence     */
34446bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence    property_set("vold.decrypt", "trigger_restart_min_framework");
3445f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    return 0;
3446f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence}
3447f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
3448f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence/* Returns type of the password, default, pattern, pin or password.
3449f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence */
3450f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrenceint cryptfs_get_password_type(void)
3451f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence{
345238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (e4crypt_is_native()) {
34537b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        SLOGE("cryptfs_get_password_type not valid for file encryption");
34547b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        return -1;
345505335c344d73411439774dfa548c633020e158e1Paul Lawrence    }
345605335c344d73411439774dfa548c633020e158e1Paul Lawrence
3457f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    struct crypt_mnt_ftr crypt_ftr;
3458f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
3459f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    if (get_crypt_ftr_and_key(&crypt_ftr)) {
3460f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGE("Error getting crypt footer and key\n");
3461f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        return -1;
3462f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    }
3463f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence
34646bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence    if (crypt_ftr.flags & CRYPT_INCONSISTENT_STATE) {
34656bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence        return -1;
34666bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence    }
34676bfed20c77184d00d948130d88d86db7ddd8a3f1Paul Lawrence
3468f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    return crypt_ftr.crypt_type;
3469f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence}
3470684dbdf316a02cf6a7694018f7c3a4bcd65142ccPaul Lawrence
347105335c344d73411439774dfa548c633020e158e1Paul Lawrenceconst char* cryptfs_get_password()
3472684dbdf316a02cf6a7694018f7c3a4bcd65142ccPaul Lawrence{
347338132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (e4crypt_is_native()) {
34747b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        SLOGE("cryptfs_get_password not valid for file encryption");
34757b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence        return 0;
347605335c344d73411439774dfa548c633020e158e1Paul Lawrence    }
347705335c344d73411439774dfa548c633020e158e1Paul Lawrence
3478399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence    struct timespec now;
3479ef2b5bea6b72331568036788c6fcaadf63f1f178Paul Lawrence    clock_gettime(CLOCK_BOOTTIME, &now);
3480399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence    if (now.tv_sec < password_expiry_time) {
3481399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        return password;
3482399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence    } else {
3483399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        cryptfs_clear_password();
3484399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        return 0;
3485399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence    }
3486399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence}
3487399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence
3488399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrencevoid cryptfs_clear_password()
3489399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence{
3490399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence    if (password) {
3491399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        size_t len = strlen(password);
3492399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        memset(password, 0, len);
3493399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        free(password);
3494399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        password = 0;
3495399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        password_expiry_time = 0;
3496399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence    }
3497684dbdf316a02cf6a7694018f7c3a4bcd65142ccPaul Lawrence}
3498731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
3499731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint cryptfs_enable_file()
3500731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
350138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    return e4crypt_initialize_global_de();
3502731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
3503731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
35040c24746627e642460b7b0b9133aee0e1da764ae4Paul Lawrenceint cryptfs_isConvertibleToFBE()
35050c24746627e642460b7b0b9133aee0e1da764ae4Paul Lawrence{
35060c24746627e642460b7b0b9133aee0e1da764ae4Paul Lawrence    struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, DATA_MNT_POINT);
35070c24746627e642460b7b0b9133aee0e1da764ae4Paul Lawrence    return fs_mgr_is_convertible_to_fbe(rec) ? 1 : 0;
35080c24746627e642460b7b0b9133aee0e1da764ae4Paul Lawrence}
35090c24746627e642460b7b0b9133aee0e1da764ae4Paul Lawrence
3510731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint cryptfs_create_default_ftr(struct crypt_mnt_ftr* crypt_ftr, __attribute__((unused))int key_length)
3511731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
3512731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (cryptfs_init_crypt_mnt_ftr(crypt_ftr)) {
3513731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Failed to initialize crypt_ftr");
3514731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
3515731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
3516731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
3517731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (create_encrypted_random_key(DEFAULT_PASSWORD, crypt_ftr->master_key,
3518731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                                    crypt_ftr->salt, crypt_ftr)) {
3519731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        SLOGE("Cannot create encrypted master key\n");
3520731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence        return -1;
3521731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
3522731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
3523731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    //crypt_ftr->keysize = key_length / 8;
3524731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return 0;
3525731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
3526731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
3527731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint cryptfs_get_master_key(struct crypt_mnt_ftr* ftr, const char* password,
3528731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                           unsigned char* master_key)
3529731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
3530731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    int rc;
3531731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
3532731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    unsigned char* intermediate_key = 0;
3533731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    size_t intermediate_key_size = 0;
3534c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence
3535c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    if (password == 0 || *password == 0) {
3536c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence        password = DEFAULT_PASSWORD;
3537c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    }
3538c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence
3539731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    rc = decrypt_master_key(password, master_key, ftr, &intermediate_key,
3540731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                            &intermediate_key_size);
3541731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
3542300dae7c38e6853148a998dfc1030b2be40490b5Paul Lawrence    if (rc) {
3543300dae7c38e6853148a998dfc1030b2be40490b5Paul Lawrence        SLOGE("Can't calculate intermediate key");
3544300dae7c38e6853148a998dfc1030b2be40490b5Paul Lawrence        return rc;
3545300dae7c38e6853148a998dfc1030b2be40490b5Paul Lawrence    }
3546300dae7c38e6853148a998dfc1030b2be40490b5Paul Lawrence
3547c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    int N = 1 << ftr->N_factor;
3548c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    int r = 1 << ftr->r_factor;
3549c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    int p = 1 << ftr->p_factor;
3550c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence
3551c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    unsigned char scrypted_intermediate_key[sizeof(ftr->scrypted_intermediate_key)];
3552c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence
3553c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    rc = crypto_scrypt(intermediate_key, intermediate_key_size,
3554c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence                       ftr->salt, sizeof(ftr->salt), N, r, p,
3555c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence                       scrypted_intermediate_key,
3556c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence                       sizeof(scrypted_intermediate_key));
3557c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence
3558c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    free(intermediate_key);
3559c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence
3560c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    if (rc) {
3561300dae7c38e6853148a998dfc1030b2be40490b5Paul Lawrence        SLOGE("Can't scrypt intermediate key");
3562c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence        return rc;
3563c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    }
3564c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence
3565c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence    return memcmp(scrypted_intermediate_key, ftr->scrypted_intermediate_key,
3566c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence                  intermediate_key_size);
3567731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
3568731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
3569731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint cryptfs_set_password(struct crypt_mnt_ftr* ftr, const char* password,
3570731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                         const unsigned char* master_key)
3571731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{
3572731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    return encrypt_master_key(password, ftr->salt, master_key, ftr->master_key,
3573731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence                              ftr);
3574731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
35756e410597343716924ed4943d1eabd3dea614d325Paul Lawrence
3576b45caafbccbb743c8b01a5287188969883dec377Eric Biggersvoid cryptfs_get_file_encryption_modes(const char **contents_mode_ret,
3577b45caafbccbb743c8b01a5287188969883dec377Eric Biggers                                       const char **filenames_mode_ret)
35786e410597343716924ed4943d1eabd3dea614d325Paul Lawrence{
35796e410597343716924ed4943d1eabd3dea614d325Paul Lawrence    struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, DATA_MNT_POINT);
3580b45caafbccbb743c8b01a5287188969883dec377Eric Biggers    fs_mgr_get_file_encryption_modes(rec, contents_mode_ret, filenames_mode_ret);
35816e410597343716924ed4943d1eabd3dea614d325Paul Lawrence}
3582