Merge RP1A.200214.001
Change-Id: Iae67f34eb591d6ec16bb2acbe483eee750711a31
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 3f24823..9166016 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -14,12 +14,6 @@
* limitations under the License.
*/
-/* TO DO:
- * 1. Perhaps keep several copies of the encrypted key, in case something
- * goes horribly wrong?
- *
- */
-
#define LOG_TAG "Cryptfs"
#include "cryptfs.h"
@@ -70,6 +64,9 @@
#include <time.h>
#include <unistd.h>
+#include <chrono>
+#include <thread>
+
#ifdef CONFIG_HW_DISK_ENCRYPTION
#include <linux/dm-ioctl.h>
#include <sys/ioctl.h>
@@ -82,9 +79,190 @@
using android::base::ParseUint;
using android::base::StringPrintf;
using android::fs_mgr::GetEntryForMountPoint;
+using android::vold::KeyBuffer;
using namespace android::dm;
using namespace std::chrono_literals;
+/* The current cryptfs version */
+#define CURRENT_MAJOR_VERSION 1
+#define CURRENT_MINOR_VERSION 3
+
+#define CRYPT_FOOTER_TO_PERSIST_OFFSET 0x1000
+#define CRYPT_PERSIST_DATA_SIZE 0x1000
+
+#define MAX_CRYPTO_TYPE_NAME_LEN 64
+
+#define MAX_KEY_LEN 48
+#define SALT_LEN 16
+#define SCRYPT_LEN 32
+
+/* definitions of flags in the structure below */
+#define CRYPT_MNT_KEY_UNENCRYPTED 0x1 /* The key for the partition is not encrypted. */
+#define CRYPT_ENCRYPTION_IN_PROGRESS \
+ 0x2 /* Encryption partially completed, \
+ encrypted_upto valid*/
+#define CRYPT_INCONSISTENT_STATE \
+ 0x4 /* Set when starting encryption, clear when \
+ exit cleanly, either through success or \
+ correctly marked partial encryption */
+#define CRYPT_DATA_CORRUPT \
+ 0x8 /* Set when encryption is fine, but the \
+ underlying volume is corrupt */
+#define CRYPT_FORCE_ENCRYPTION \
+ 0x10 /* Set when it is time to encrypt this \
+ volume on boot. Everything in this \
+ structure is set up correctly as \
+ though device is encrypted except \
+ that the master key is encrypted with the \
+ default password. */
+#define CRYPT_FORCE_COMPLETE \
+ 0x20 /* Set when the above encryption cycle is \
+ complete. On next cryptkeeper entry, match \
+ the password. If it matches fix the master \
+ key and remove this flag. */
+
+/* Allowed values for type in the structure below */
+#define CRYPT_TYPE_PASSWORD \
+ 0 /* master_key is encrypted with a password \
+ * Must be zero to be compatible with pre-L \
+ * devices where type is always password.*/
+#define CRYPT_TYPE_DEFAULT \
+ 1 /* master_key is encrypted with default \
+ * password */
+#define CRYPT_TYPE_PATTERN 2 /* master_key is encrypted with a pattern */
+#define CRYPT_TYPE_PIN 3 /* master_key is encrypted with a pin */
+#define CRYPT_TYPE_MAX_TYPE 3 /* type cannot be larger than this value */
+
+#define CRYPT_MNT_MAGIC 0xD0B5B1C4
+#define PERSIST_DATA_MAGIC 0xE950CD44
+
+/* Key Derivation Function algorithms */
+#define KDF_PBKDF2 1
+#define KDF_SCRYPT 2
+/* Algorithms 3 & 4 deprecated before shipping outside of google, so removed */
+#define KDF_SCRYPT_KEYMASTER 5
+
+/* Maximum allowed keymaster blob size. */
+#define KEYMASTER_BLOB_SIZE 2048
+
+/* __le32 and __le16 defined in system/extras/ext4_utils/ext4_utils.h */
+#define __le8 unsigned char
+
+#if !defined(SHA256_DIGEST_LENGTH)
+#define SHA256_DIGEST_LENGTH 32
+#endif
+
+/* This structure starts 16,384 bytes before the end of a hardware
+ * partition that is encrypted, or in a separate partition. It's location
+ * is specified by a property set in init.<device>.rc.
+ * The structure allocates 48 bytes for a key, but the real key size is
+ * specified in the struct. Currently, the code is hardcoded to use 128
+ * bit keys.
+ * The fields after salt are only valid in rev 1.1 and later stuctures.
+ * Obviously, the filesystem does not include the last 16 kbytes
+ * of the partition if the crypt_mnt_ftr lives at the end of the
+ * partition.
+ */
+
+struct crypt_mnt_ftr {
+ __le32 magic; /* See above */
+ __le16 major_version;
+ __le16 minor_version;
+ __le32 ftr_size; /* in bytes, not including key following */
+ __le32 flags; /* See above */
+ __le32 keysize; /* in bytes */
+ __le32 crypt_type; /* how master_key is encrypted. Must be a
+ * CRYPT_TYPE_XXX value */
+ __le64 fs_size; /* Size of the encrypted fs, in 512 byte sectors */
+ __le32 failed_decrypt_count; /* count of # of failed attempts to decrypt and
+ mount, set to 0 on successful mount */
+ unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption
+ needed to decrypt this
+ partition, null terminated */
+ __le32 spare2; /* ignored */
+ unsigned char master_key[MAX_KEY_LEN]; /* The encrypted key for decrypting the filesystem */
+ unsigned char salt[SALT_LEN]; /* The salt used for this encryption */
+ __le64 persist_data_offset[2]; /* Absolute offset to both copies of crypt_persist_data
+ * on device with that info, either the footer of the
+ * real_blkdevice or the metadata partition. */
+
+ __le32 persist_data_size; /* The number of bytes allocated to each copy of the
+ * persistent data table*/
+
+ __le8 kdf_type; /* The key derivation function used. */
+
+ /* scrypt parameters. See www.tarsnap.com/scrypt/scrypt.pdf */
+ __le8 N_factor; /* (1 << N) */
+ __le8 r_factor; /* (1 << r) */
+ __le8 p_factor; /* (1 << p) */
+ __le64 encrypted_upto; /* If we are in state CRYPT_ENCRYPTION_IN_PROGRESS and
+ we have to stop (e.g. power low) this is the last
+ encrypted 512 byte sector.*/
+ __le8 hash_first_block[SHA256_DIGEST_LENGTH]; /* When CRYPT_ENCRYPTION_IN_PROGRESS
+ set, hash of first block, used
+ to validate before continuing*/
+
+ /* key_master key, used to sign the derived key which is then used to generate
+ * the intermediate key
+ * This key should be used for no other purposes! We use this key to sign unpadded
+ * data, which is acceptable but only if the key is not reused elsewhere. */
+ __le8 keymaster_blob[KEYMASTER_BLOB_SIZE];
+ __le32 keymaster_blob_size;
+
+ /* Store scrypt of salted intermediate key. When decryption fails, we can
+ check if this matches, and if it does, we know that the problem is with the
+ drive, and there is no point in asking the user for more passwords.
+
+ Note that if any part of this structure is corrupt, this will not match and
+ we will continue to believe the user entered the wrong password. In that
+ case the only solution is for the user to enter a password enough times to
+ force a wipe.
+
+ Note also that there is no need to worry about migration. If this data is
+ wrong, we simply won't recognise a right password, and will continue to
+ prompt. On the first password change, this value will be populated and
+ then we will be OK.
+ */
+ unsigned char scrypted_intermediate_key[SCRYPT_LEN];
+
+ /* sha of this structure with this element set to zero
+ Used when encrypting on reboot to validate structure before doing something
+ fatal
+ */
+ unsigned char sha256[SHA256_DIGEST_LENGTH];
+};
+
+/* Persistant data that should be available before decryption.
+ * Things like airplane mode, locale and timezone are kept
+ * here and can be retrieved by the CryptKeeper UI to properly
+ * configure the phone before asking for the password
+ * This is only valid if the major and minor version above
+ * is set to 1.1 or higher.
+ *
+ * This is a 4K structure. There are 2 copies, and the code alternates
+ * writing one and then clearing the previous one. The reading
+ * code reads the first valid copy it finds, based on the magic number.
+ * The absolute offset to the first of the two copies is kept in rev 1.1
+ * and higher crypt_mnt_ftr structures.
+ */
+struct crypt_persist_entry {
+ char key[PROPERTY_KEY_MAX];
+ char val[PROPERTY_VALUE_MAX];
+};
+
+/* Should be exactly 4K in size */
+struct crypt_persist_data {
+ __le32 persist_magic;
+ __le32 persist_valid_entries;
+ __le32 persist_spare[30];
+ struct crypt_persist_entry persist_entry[0];
+};
+
+static int wait_and_unmount(const char* mountpoint, bool kill);
+
+typedef int (*kdf_func)(const char* passwd, const unsigned char* salt, unsigned char* ikey,
+ void* params);
+
#define UNUSED __attribute__((unused))
#define HASH_COUNT 2000
@@ -1307,8 +1485,8 @@
#endif
static int create_crypto_blk_dev(struct crypt_mnt_ftr* crypt_ftr, const unsigned char* master_key,
- const char* real_blk_name, char* crypto_blk_name, const char* name,
- uint32_t flags) {
+ const char* real_blk_name, std::string* crypto_blk_name,
+ const char* name, uint32_t flags) {
auto& dm = DeviceMapper::Instance();
// We need two ASCII characters to represent each byte, and need space for
@@ -1348,15 +1526,13 @@
SLOGI("Took %d tries to load dmcrypt table.\n", load_count);
}
- std::string path;
- if (!dm.GetDmDevicePathByName(name, &path)) {
+ if (!dm.GetDmDevicePathByName(name, crypto_blk_name)) {
SLOGE("Cannot determine dm-crypt path for %s.\n", name);
return -1;
}
- snprintf(crypto_blk_name, MAXPATHLEN, "%s", path.c_str());
/* Ensure the dm device has been created before returning. */
- if (android::vold::WaitForFile(crypto_blk_name, 1s) < 0) {
+ if (android::vold::WaitForFile(crypto_blk_name->c_str(), 1s) < 0) {
// WaitForFile generates a suitable log message
return -1;
}
@@ -1364,9 +1540,22 @@
}
static int delete_crypto_blk_dev(const std::string& name) {
+ bool ret;
auto& dm = DeviceMapper::Instance();
- if (!dm.DeleteDevice(name)) {
- SLOGE("Cannot remove dm-crypt device %s: %s\n", name.c_str(), strerror(errno));
+ // TODO(b/149396179) there appears to be a race somewhere in the system where trying
+ // to delete the device fails with EBUSY; for now, work around this by retrying.
+ int tries = 5;
+ while (tries-- > 0) {
+ ret = dm.DeleteDevice(name);
+ if (ret || errno != EBUSY) {
+ break;
+ }
+ SLOGW("DM_DEV Cannot remove dm-crypt device %s: %s, retrying...\n", name.c_str(),
+ strerror(errno));
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ if (!ret) {
+ SLOGE("DM_DEV Cannot remove dm-crypt device %s: %s\n", name.c_str(), strerror(errno));
return -1;
}
return 0;
@@ -1616,7 +1805,7 @@
return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr, true);
}
-int wait_and_unmount(const char* mountpoint, bool kill) {
+static int wait_and_unmount(const char* mountpoint, bool kill) {
int i, err, rc;
#define WAIT_UNMOUNT_COUNT 200
@@ -1970,7 +2159,8 @@
{
/* Allocate enough space for a 256 bit key, but we may use less */
unsigned char decrypted_master_key[32];
- char crypto_blkdev[MAXPATHLEN];
+ char crypto_blkdev_hw[MAXPATHLEN];
+ std::string crypto_blkdev;
std::string real_blkdev;
unsigned int orig_failed_decrypt_count;
int rc = 0;
@@ -1991,7 +2181,7 @@
if (is_ice_enabled()) {
#ifndef CONFIG_HW_DISK_ENCRYPT_PERF
if (create_crypto_blk_dev_hw(crypt_ftr, (unsigned char*)&key_index,
- real_blkdev.c_str(), crypto_blkdev, label, 0)) {
+ real_blkdev.c_str(), crypto_blkdev_hw, label, 0)) {
SLOGE("Error creating decrypted block device");
rc = -1;
goto errout;
@@ -1999,7 +2189,7 @@
#endif
} else {
if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
- real_blkdev.c_str(), crypto_blkdev, label, 0)) {
+ real_blkdev.c_str(), &crypto_blkdev, label, 0)) {
SLOGE("Error creating decrypted block device");
rc = -1;
goto errout;
@@ -2018,8 +2208,10 @@
* so we can mount it when restarting the framework. */
#ifdef CONFIG_HW_DISK_ENCRYPT_PERF
if (!is_ice_enabled())
-#endif
+ property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev_hw);
+#else
property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev);
+#endif
master_key_saved = 1;
}
@@ -2031,7 +2223,7 @@
static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, const char* passwd,
const char* mount_point, const char* label) {
unsigned char decrypted_master_key[MAX_KEY_LEN];
- char crypto_blkdev[MAXPATHLEN];
+ std::string crypto_blkdev;
std::string real_blkdev;
char tmp_mount_point[64];
unsigned int orig_failed_decrypt_count;
@@ -2060,7 +2252,7 @@
// Create crypto block device - all (non fatal) code paths
// need it
- if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key, real_blkdev.c_str(), crypto_blkdev,
+ if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key, real_blkdev.c_str(), &crypto_blkdev,
label, 0)) {
SLOGE("Error creating decrypted block device\n");
rc = -1;
@@ -2084,7 +2276,8 @@
* the footer, not the key. */
snprintf(tmp_mount_point, sizeof(tmp_mount_point), "%s/tmp_mnt", mount_point);
mkdir(tmp_mount_point, 0755);
- if (fs_mgr_do_mount(&fstab_default, DATA_MNT_POINT, crypto_blkdev, tmp_mount_point)) {
+ if (fs_mgr_do_mount(&fstab_default, DATA_MNT_POINT,
+ const_cast<char*>(crypto_blkdev.c_str()), tmp_mount_point)) {
SLOGE("Error temp mounting decrypted block device\n");
delete_crypto_blk_dev(label);
@@ -2106,7 +2299,7 @@
/* Save the name of the crypto block device
* so we can mount it when restarting the framework. */
- property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev);
+ property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev.c_str());
/* Also save a the master key so we can reencrypted the key
* the key when we want to change the password on it. */
@@ -2163,11 +2356,14 @@
* storage volume. The incoming partition has no crypto header/footer,
* as any metadata is been stored in a separate, small partition. We
* assume it must be using our same crypt type and keysize.
- *
- * out_crypto_blkdev must be MAXPATHLEN.
*/
-int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const unsigned char* key,
- char* out_crypto_blkdev) {
+int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const KeyBuffer& key,
+ std::string* out_crypto_blkdev) {
+ if (key.size() != cryptfs_get_keysize()) {
+ SLOGE("Raw keysize %zu does not match crypt keysize %" PRIu32, key.size(),
+ cryptfs_get_keysize());
+ return -1;
+ }
uint64_t nr_sec = 0;
if (android::vold::GetBlockDev512Sectors(real_blkdev, &nr_sec) != android::OK) {
SLOGE("Failed to get size of %s: %s", real_blkdev, strerror(errno));
@@ -2185,15 +2381,8 @@
android::base::GetBoolProperty("ro.crypto.allow_encrypt_override", false))
flags |= CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE;
- return create_crypto_blk_dev(&ext_crypt_ftr, key, real_blkdev, out_crypto_blkdev, label, flags);
-}
-
-/*
- * Called by vold when it's asked to unmount an encrypted external
- * storage volume.
- */
-int cryptfs_revert_ext_volume(const char* label) {
- return delete_crypto_blk_dev(label);
+ return create_crypto_blk_dev(&ext_crypt_ftr, reinterpret_cast<const unsigned char*>(key.data()),
+ real_blkdev, out_crypto_blkdev, label, flags);
}
int cryptfs_crypto_complete(void) {
@@ -2469,8 +2658,8 @@
return 0;
}
-static int cryptfs_enable_all_volumes(struct crypt_mnt_ftr* crypt_ftr, char* crypto_blkdev,
- char* real_blkdev, int previously_encrypted_upto) {
+static int cryptfs_enable_all_volumes(struct crypt_mnt_ftr* crypt_ftr, const char* crypto_blkdev,
+ const char* real_blkdev, int previously_encrypted_upto) {
off64_t cur_encryption_done = 0, tot_encryption_size = 0;
int rc = -1;
@@ -2505,7 +2694,7 @@
}
int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
- char crypto_blkdev[MAXPATHLEN];
+ std::string crypto_blkdev;
std::string real_blkdev;
unsigned char decrypted_master_key[MAX_KEY_LEN];
int rc = -1, i;
@@ -2772,16 +2961,16 @@
#ifdef CONFIG_HW_DISK_ENCRYPTION
if (is_hw_disk_encryption((char*)crypt_ftr.crypto_type_name) && is_ice_enabled())
#ifdef CONFIG_HW_DISK_ENCRYPT_PERF
- strlcpy(crypto_blkdev, real_blkdev.c_str(), sizeof(crypto_blkdev));
+ crypto_blkdev = real_blkdev;
#else
- create_crypto_blk_dev_hw(&crypt_ftr, (unsigned char*)&key_index, real_blkdev.c_str(), crypto_blkdev,
+ create_crypto_blk_dev_hw(&crypt_ftr, (unsigned char*)&key_index, real_blkdev.c_str(), &crypto_blkdev,
CRYPTO_BLOCK_DEVICE, 0);
#endif
else
- create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev.c_str(), crypto_blkdev,
+ create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev.c_str(), &crypto_blkdev,
CRYPTO_BLOCK_DEVICE, 0);
#else
- create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev.c_str(), crypto_blkdev,
+ create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev.c_str(), &crypto_blkdev,
CRYPTO_BLOCK_DEVICE, 0);
#endif
@@ -2795,7 +2984,7 @@
goto error_shutting_down;
}
#endif
- rc = cryptfs_SHA256_fileblock(crypto_blkdev, hash_first_block);
+ rc = cryptfs_SHA256_fileblock(crypto_blkdev.c_str(), hash_first_block);
if (!rc &&
memcmp(hash_first_block, crypt_ftr.hash_first_block, sizeof(hash_first_block)) != 0) {
@@ -2811,7 +3000,7 @@
}
#endif
if (!rc) {
- rc = cryptfs_enable_all_volumes(&crypt_ftr, crypto_blkdev, real_blkdev.data(),
+ rc = cryptfs_enable_all_volumes(&crypt_ftr, crypto_blkdev.c_str(), real_blkdev.data(),
previously_encrypted_upto);
}
@@ -2823,7 +3012,7 @@
#endif
/* Calculate checksum if we are not finished */
if (!rc && crypt_ftr.encrypted_upto != crypt_ftr.fs_size) {
- rc = cryptfs_SHA256_fileblock(crypto_blkdev, crypt_ftr.hash_first_block);
+ rc = cryptfs_SHA256_fileblock(crypto_blkdev.c_str(), crypt_ftr.hash_first_block);
if (rc) {
SLOGE("Error calculating checksum for continuing encryption");
rc = -1;