Merge "vold: Use the new method of rebooting by asking init to do it"
diff --git a/Android.mk b/Android.mk
index 098c3d0..ba9b0a1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,13 +15,15 @@
Devmapper.cpp \
ResponseCode.cpp \
Xwarp.cpp \
+ VoldUtil.c \
fstrim.c \
cryptfs.c
common_c_includes := \
$(KERNEL_HEADERS) \
system/extras/ext4_utils \
- external/openssl/include
+ external/openssl/include \
+ external/scrypt/lib/crypto
common_shared_libraries := \
libsysutils \
@@ -32,6 +34,10 @@
liblogwrap \
libcrypto
+common_static_libraries := \
+ libfs_mgr \
+ libscrypt_static
+
include $(CLEAR_VARS)
LOCAL_MODULE := libvold
@@ -42,7 +48,7 @@
LOCAL_SHARED_LIBRARIES := $(common_shared_libraries)
-LOCAL_STATIC_LIBRARIES := libfs_mgr
+LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
LOCAL_MODULE_TAGS := eng tests
@@ -62,7 +68,7 @@
LOCAL_SHARED_LIBRARIES := $(common_shared_libraries)
-LOCAL_STATIC_LIBRARIES := libfs_mgr
+LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
include $(BUILD_EXECUTABLE)
diff --git a/CommandListener.cpp b/CommandListener.cpp
index f306527..5de920f 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -162,11 +162,16 @@
}
rc = vm->unmountVolume(argv[2], force, revert);
} else if (!strcmp(argv[1], "format")) {
- if (argc != 3) {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format <path>", false);
+ if (argc < 3 || argc > 4 ||
+ (argc == 4 && strcmp(argv[3], "wipe"))) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format <path> [wipe]", false);
return 0;
}
- rc = vm->formatVolume(argv[2]);
+ bool wipe = false;
+ if (argc >= 4 && !strcmp(argv[3], "wipe")) {
+ wipe = true;
+ }
+ rc = vm->formatVolume(argv[2], wipe);
} else if (!strcmp(argv[1], "share")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
diff --git a/Fat.cpp b/Fat.cpp
index 807f440..c967a90 100644
--- a/Fat.cpp
+++ b/Fat.cpp
@@ -30,6 +30,8 @@
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/wait.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
#include <linux/kdev_t.h>
@@ -167,12 +169,16 @@
return rc;
}
-int Fat::format(const char *fsPath, unsigned int numSectors) {
+int Fat::format(const char *fsPath, unsigned int numSectors, bool wipe) {
int fd;
const char *args[10];
int rc;
int status;
+ if (wipe) {
+ Fat::wipe(fsPath, numSectors);
+ }
+
args[0] = MKDOSFS_PATH;
args[1] = "-F";
args[2] = "32";
@@ -220,3 +226,30 @@
}
return 0;
}
+
+void Fat::wipe(const char *fsPath, unsigned int numSectors) {
+ int fd;
+ unsigned long long range[2];
+
+ fd = open(fsPath, O_RDWR);
+ if (fd >= 0) {
+ if (numSectors == 0) {
+ numSectors = get_blkdev_size(fd);
+ }
+ if (numSectors == 0) {
+ SLOGE("Fat wipe failed to determine size of %s", fsPath);
+ close(fd);
+ return;
+ }
+ range[0] = 0;
+ range[1] = (unsigned long long)numSectors * 512;
+ if (ioctl(fd, BLKDISCARD, &range) < 0) {
+ SLOGE("Fat wipe failed to discard blocks on %s", fsPath);
+ } else {
+ SLOGI("Fat wipe %d sectors on %s succeeded", numSectors, fsPath);
+ }
+ close(fd);
+ } else {
+ SLOGE("Fat wipe failed to open device %s", fsPath);
+ }
+}
diff --git a/Fat.h b/Fat.h
index e02d88c..19614d1 100644
--- a/Fat.h
+++ b/Fat.h
@@ -26,7 +26,10 @@
bool ro, bool remount, bool executable,
int ownerUid, int ownerGid, int permMask,
bool createLost);
- static int format(const char *fsPath, unsigned int numSectors);
+ static int format(const char *fsPath, unsigned int numSectors, bool wipe);
+
+private:
+ static void wipe(const char *fsPath, unsigned int numSectors);
};
#endif
diff --git a/VoldUtil.c b/VoldUtil.c
new file mode 100644
index 0000000..b5f9946
--- /dev/null
+++ b/VoldUtil.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+
+unsigned int get_blkdev_size(int fd)
+{
+ unsigned int nr_sec;
+
+ if ( (ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
+ nr_sec = 0;
+ }
+
+ return nr_sec;
+}
diff --git a/VoldUtil.h b/VoldUtil.h
index 30a3add..469489a 100644
--- a/VoldUtil.h
+++ b/VoldUtil.h
@@ -17,6 +17,12 @@
#ifndef _VOLDUTIL_H
#define _VOLDUTIL_H
+#include <sys/cdefs.h>
+
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+__BEGIN_DECLS
+ unsigned int get_blkdev_size(int fd);
+__END_DECLS
+
#endif
diff --git a/Volume.cpp b/Volume.cpp
index 4a00ccc..4501e90 100644
--- a/Volume.cpp
+++ b/Volume.cpp
@@ -206,7 +206,7 @@
return 0;
}
-int Volume::formatVol() {
+int Volume::formatVol(bool wipe) {
if (getState() == Volume::State_NoMedia) {
errno = ENODEV;
@@ -250,7 +250,7 @@
SLOGI("Formatting volume %s (%s)", getLabel(), devicePath);
}
- if (Fat::format(devicePath, 0)) {
+ if (Fat::format(devicePath, 0, wipe)) {
SLOGE("Failed to format (%s)", strerror(errno));
goto err;
}
diff --git a/Volume.h b/Volume.h
index c717d4d..22e247d 100644
--- a/Volume.h
+++ b/Volume.h
@@ -67,7 +67,7 @@
int mountVol();
int unmountVol(bool force, bool revert);
- int formatVol();
+ int formatVol(bool wipe);
const char *getLabel() { return mLabel; }
const char *getMountpoint() { return mMountpoint; }
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index a1930d1..180387c 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -167,7 +167,7 @@
return 0;
}
-int VolumeManager::formatVolume(const char *label) {
+int VolumeManager::formatVolume(const char *label, bool wipe) {
Volume *v = lookupVolume(label);
if (!v) {
@@ -180,7 +180,7 @@
return -1;
}
- return v->formatVol();
+ return v->formatVol(wipe);
}
int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
@@ -414,7 +414,7 @@
if (usingExt4) {
formatStatus = Ext4::format(dmDevice, mountPoint);
} else {
- formatStatus = Fat::format(dmDevice, numImgSectors);
+ formatStatus = Fat::format(dmDevice, numImgSectors, 0);
}
if (formatStatus < 0) {
diff --git a/VolumeManager.h b/VolumeManager.h
index 198b5a9..be78516 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -83,7 +83,7 @@
int shareVolume(const char *label, const char *method);
int unshareVolume(const char *label, const char *method);
int shareEnabled(const char *path, const char *method, bool *enabled);
- int formatVolume(const char *label);
+ int formatVolume(const char *label, bool wipe);
void disableVolumeManager(void) { mVolManagerDisabled = 1; }
/* ASEC */
diff --git a/cryptfs.c b/cryptfs.c
index 2f8381c..266481d 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -45,6 +45,8 @@
#include "cutils/android_reboot.h"
#include "hardware_legacy/power.h"
#include "VolumeManager.h"
+#include "VoldUtil.h"
+#include "crypto_scrypt.h"
#define DM_CRYPT_BUF_SIZE 4096
#define DATA_MNT_POINT "/data"
@@ -96,6 +98,55 @@
}
}
+/**
+ * Gets the default device scrypt parameters for key derivation time tuning.
+ * The parameters should lead to about one second derivation time for the
+ * given device.
+ */
+static void get_device_scrypt_params(struct crypt_mnt_ftr *ftr) {
+ const int default_params[] = SCRYPT_DEFAULTS;
+ int params[] = SCRYPT_DEFAULTS;
+ char paramstr[PROPERTY_VALUE_MAX];
+ char *token;
+ char *saveptr;
+ int i;
+
+ property_get(SCRYPT_PROP, paramstr, "");
+ if (paramstr[0] != '\0') {
+ /*
+ * The token we're looking for should be three integers separated by
+ * colons (e.g., "12:8:1"). Scan the property to make sure it matches.
+ */
+ for (token = strtok_r(paramstr, ":", &saveptr); token != NULL && i < 3;
+ i++, token = strtok_r(NULL, ":", &saveptr)) {
+ char *endptr;
+ params[i] = strtol(token, &endptr, 10);
+
+ /*
+ * Check that there was a valid number and it's 8-bit. If not,
+ * break out and the end check will take the default values.
+ */
+ if ((*token == '\0') || (*endptr != '\0') || params[i] < 0 || params[i] > 255) {
+ break;
+ }
+ }
+
+ /*
+ * If there were not enough tokens or a token was malformed (not an
+ * integer), it will end up here and the default parameters can be
+ * taken.
+ */
+ if ((i != 3) || (token != NULL)) {
+ SLOGW("bad scrypt parameters '%s' should be like '12:8:1'; using defaults", paramstr);
+ memcpy(params, default_params, sizeof(params));
+ }
+ }
+
+ ftr->N_factor = params[0];
+ ftr->r_factor = params[1];
+ ftr->p_factor = params[2];
+}
+
static unsigned int get_fs_size(char *dev)
{
int fd, block_size;
@@ -127,17 +178,6 @@
return (unsigned int) (len / 512);
}
-static unsigned int get_blkdev_size(int fd)
-{
- unsigned int nr_sec;
-
- if ( (ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
- nr_sec = 0;
- }
-
- return nr_sec;
-}
-
static int get_crypt_ftr_info(char **metadata_fname, off64_t *off)
{
static int cached_data = 0;
@@ -272,46 +312,55 @@
*/
static void upgrade_crypt_ftr(int fd, struct crypt_mnt_ftr *crypt_ftr, off64_t offset)
{
- struct crypt_persist_data *pdata;
- off64_t pdata_offset = offset + CRYPT_FOOTER_TO_PERSIST_OFFSET;
+ int orig_major = crypt_ftr->major_version;
+ int orig_minor = crypt_ftr->minor_version;
- /* This routine can currently only handle upgrading from 1.0 to 1.1.
- * Do nothing if the passed structure is not version 1.0
- */
+ if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 0)) {
+ struct crypt_persist_data *pdata;
+ off64_t pdata_offset = offset + CRYPT_FOOTER_TO_PERSIST_OFFSET;
- if ((crypt_ftr->major_version != 1) && (crypt_ftr->minor_version != 0)) {
- return;
+ SLOGW("upgrading crypto footer to 1.1");
+
+ pdata = malloc(CRYPT_PERSIST_DATA_SIZE);
+ if (pdata == NULL) {
+ SLOGE("Cannot allocate persisent data\n");
+ return;
+ }
+ memset(pdata, 0, CRYPT_PERSIST_DATA_SIZE);
+
+ /* Need to initialize the persistent data area */
+ if (lseek64(fd, pdata_offset, SEEK_SET) == -1) {
+ SLOGE("Cannot seek to persisent data offset\n");
+ return;
+ }
+ /* Write all zeros to the first copy, making it invalid */
+ unix_write(fd, pdata, CRYPT_PERSIST_DATA_SIZE);
+
+ /* Write a valid but empty structure to the second copy */
+ init_empty_persist_data(pdata, CRYPT_PERSIST_DATA_SIZE);
+ unix_write(fd, pdata, CRYPT_PERSIST_DATA_SIZE);
+
+ /* Update the footer */
+ crypt_ftr->persist_data_size = CRYPT_PERSIST_DATA_SIZE;
+ crypt_ftr->persist_data_offset[0] = pdata_offset;
+ crypt_ftr->persist_data_offset[1] = pdata_offset + CRYPT_PERSIST_DATA_SIZE;
+ crypt_ftr->minor_version = 1;
}
- pdata = malloc(CRYPT_PERSIST_DATA_SIZE);
- if (pdata == NULL) {
- SLOGE("Cannot allocate persisent data\n");
- return;
+ if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version)) {
+ SLOGW("upgrading crypto footer to 1.2");
+ crypt_ftr->kdf_type = KDF_PBKDF2;
+ get_device_scrypt_params(crypt_ftr);
+ crypt_ftr->minor_version = 2;
}
- memset(pdata, 0, CRYPT_PERSIST_DATA_SIZE);
- /* Need to initialize the persistent data area */
- if (lseek64(fd, pdata_offset, SEEK_SET) == -1) {
- SLOGE("Cannot seek to persisent data offset\n");
- return;
+ if ((orig_major != crypt_ftr->major_version) || (orig_minor != crypt_ftr->minor_version)) {
+ if (lseek64(fd, offset, SEEK_SET) == -1) {
+ SLOGE("Cannot seek to crypt footer\n");
+ return;
+ }
+ unix_write(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr));
}
- /* Write all zeros to the first copy, making it invalid */
- unix_write(fd, pdata, CRYPT_PERSIST_DATA_SIZE);
-
- /* Write a valid but empty structure to the second copy */
- init_empty_persist_data(pdata, CRYPT_PERSIST_DATA_SIZE);
- unix_write(fd, pdata, CRYPT_PERSIST_DATA_SIZE);
-
- /* Update the footer */
- crypt_ftr->persist_data_size = CRYPT_PERSIST_DATA_SIZE;
- crypt_ftr->persist_data_offset[0] = pdata_offset;
- crypt_ftr->persist_data_offset[1] = pdata_offset + CRYPT_PERSIST_DATA_SIZE;
- crypt_ftr->minor_version = 1;
- if (lseek64(fd, offset, SEEK_SET) == -1) {
- SLOGE("Cannot seek to crypt footer\n");
- return;
- }
- unix_write(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr));
}
@@ -361,21 +410,21 @@
goto errout;
}
- if (crypt_ftr->major_version != 1) {
- SLOGE("Cannot understand major version %d real block device footer\n",
- crypt_ftr->major_version);
+ if (crypt_ftr->major_version != CURRENT_MAJOR_VERSION) {
+ SLOGE("Cannot understand major version %d real block device footer; expected %d\n",
+ crypt_ftr->major_version, CURRENT_MAJOR_VERSION);
goto errout;
}
- if ((crypt_ftr->minor_version != 0) && (crypt_ftr->minor_version != 1)) {
- SLOGW("Warning: crypto footer minor version %d, expected 0 or 1, continuing...\n",
- crypt_ftr->minor_version);
+ if (crypt_ftr->minor_version > CURRENT_MINOR_VERSION) {
+ SLOGW("Warning: crypto footer minor version %d, expected <= %d, continuing...\n",
+ crypt_ftr->minor_version, CURRENT_MINOR_VERSION);
}
/* If this is a verion 1.0 crypt_ftr, make it a 1.1 crypt footer, and update the
* copy on disk before returning.
*/
- if (crypt_ftr->minor_version == 0) {
+ if (crypt_ftr->minor_version < CURRENT_MINOR_VERSION) {
upgrade_crypt_ftr(fd, crypt_ftr, starting_off);
}
@@ -815,24 +864,37 @@
}
-static void pbkdf2(char *passwd, unsigned char *salt, unsigned char *ikey)
-{
+static void pbkdf2(char *passwd, unsigned char *salt, unsigned char *ikey, void *params) {
/* Turn the password into a key and IV that can decrypt the master key */
PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), salt, SALT_LEN,
HASH_COUNT, KEY_LEN_BYTES+IV_LEN_BYTES, ikey);
}
+static void scrypt(char *passwd, unsigned char *salt, unsigned char *ikey, void *params) {
+ struct crypt_mnt_ftr *ftr = (struct crypt_mnt_ftr *) params;
+
+ int N = 1 << ftr->N_factor;
+ int r = 1 << ftr->r_factor;
+ int p = 1 << ftr->p_factor;
+
+ /* Turn the password into a key and IV that can decrypt the master key */
+ crypto_scrypt((unsigned char *) passwd, strlen(passwd), salt, SALT_LEN, N, r, p, ikey,
+ KEY_LEN_BYTES + IV_LEN_BYTES);
+}
+
static int encrypt_master_key(char *passwd, unsigned char *salt,
unsigned char *decrypted_master_key,
- unsigned char *encrypted_master_key)
+ unsigned char *encrypted_master_key,
+ struct crypt_mnt_ftr *crypt_ftr)
{
unsigned char ikey[32+32] = { 0 }; /* Big enough to hold a 256 bit key and 256 bit IV */
EVP_CIPHER_CTX e_ctx;
int encrypted_len, final_len;
/* Turn the password into a key and IV that can decrypt the master key */
- pbkdf2(passwd, salt, ikey);
-
+ get_device_scrypt_params(crypt_ftr);
+ scrypt(passwd, salt, ikey, crypt_ftr);
+
/* Initialize the decryption engine */
if (! EVP_EncryptInit(&e_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) {
SLOGE("EVP_EncryptInit failed\n");
@@ -861,14 +923,15 @@
static int decrypt_master_key(char *passwd, unsigned char *salt,
unsigned char *encrypted_master_key,
- unsigned char *decrypted_master_key)
+ unsigned char *decrypted_master_key,
+ kdf_func kdf, void *kdf_params)
{
unsigned char ikey[32+32] = { 0 }; /* Big enough to hold a 256 bit key and 256 bit IV */
EVP_CIPHER_CTX d_ctx;
int decrypted_len, final_len;
/* Turn the password into a key and IV that can decrypt the master key */
- pbkdf2(passwd, salt, ikey);
+ kdf(passwd, salt, ikey, kdf_params);
/* Initialize the decryption engine */
if (! EVP_DecryptInit(&d_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) {
@@ -891,8 +954,47 @@
}
}
-static int create_encrypted_random_key(char *passwd, unsigned char *master_key, unsigned char *salt)
+static void get_kdf_func(struct crypt_mnt_ftr *ftr, kdf_func *kdf, void** kdf_params)
{
+ if (ftr->kdf_type == KDF_SCRYPT) {
+ *kdf = scrypt;
+ *kdf_params = ftr;
+ } else {
+ *kdf = pbkdf2;
+ *kdf_params = NULL;
+ }
+}
+
+static int decrypt_master_key_and_upgrade(char *passwd, unsigned char *decrypted_master_key,
+ struct crypt_mnt_ftr *crypt_ftr)
+{
+ kdf_func kdf;
+ void *kdf_params;
+ int ret;
+
+ get_kdf_func(crypt_ftr, &kdf, &kdf_params);
+ ret = decrypt_master_key(passwd, crypt_ftr->salt, crypt_ftr->master_key, decrypted_master_key, kdf,
+ kdf_params);
+ if (ret != 0) {
+ SLOGW("failure decrypting master key");
+ return ret;
+ }
+
+ /*
+ * Upgrade if we're not using the latest KDF.
+ */
+ if (crypt_ftr->kdf_type != KDF_SCRYPT) {
+ crypt_ftr->kdf_type = KDF_SCRYPT;
+ encrypt_master_key(passwd, crypt_ftr->salt, decrypted_master_key, crypt_ftr->master_key,
+ crypt_ftr);
+ put_crypt_ftr_and_key(crypt_ftr);
+ }
+
+ return ret;
+}
+
+static int create_encrypted_random_key(char *passwd, unsigned char *master_key, unsigned char *salt,
+ struct crypt_mnt_ftr *crypt_ftr) {
int fd;
unsigned char key_buf[KEY_LEN_BYTES];
EVP_CIPHER_CTX e_ctx;
@@ -905,7 +1007,7 @@
close(fd);
/* Now encrypt it with the password */
- return encrypt_master_key(passwd, salt, key_buf, master_key);
+ return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr);
}
static int wait_and_unmount(char *mountpoint)
@@ -1107,6 +1209,8 @@
unsigned int orig_failed_decrypt_count;
char encrypted_state[PROPERTY_VALUE_MAX];
int rc;
+ kdf_func kdf;
+ void *kdf_params;
property_get("ro.crypto.state", encrypted_state, "");
if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) {
@@ -1125,7 +1229,7 @@
orig_failed_decrypt_count = crypt_ftr.failed_decrypt_count;
if (! (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) ) {
- decrypt_master_key(passwd, crypt_ftr.salt, crypt_ftr.master_key, decrypted_master_key);
+ decrypt_master_key_and_upgrade(passwd, decrypted_master_key, &crypt_ftr);
}
if (create_crypto_blk_dev(&crypt_ftr, decrypted_master_key,
@@ -1278,8 +1382,7 @@
/* If the device has no password, then just say the password is valid */
rc = 0;
} else {
- decrypt_master_key(passwd, crypt_ftr.salt, crypt_ftr.master_key,
- decrypted_master_key);
+ decrypt_master_key_and_upgrade(passwd, decrypted_master_key, &crypt_ftr);
if (!memcmp(decrypted_master_key, saved_master_key, crypt_ftr.keysize)) {
/* They match, the password is correct */
rc = 0;
@@ -1304,11 +1407,14 @@
memset(ftr, 0, sizeof(struct crypt_mnt_ftr));
ftr->magic = CRYPT_MNT_MAGIC;
- ftr->major_version = 1;
- ftr->minor_version = 1;
+ ftr->major_version = CURRENT_MAJOR_VERSION;
+ ftr->minor_version = CURRENT_MINOR_VERSION;
ftr->ftr_size = sizeof(struct crypt_mnt_ftr);
ftr->keysize = KEY_LEN_BYTES;
+ ftr->kdf_type = KDF_SCRYPT;
+ get_device_scrypt_params(ftr);
+
ftr->persist_data_size = CRYPT_PERSIST_DATA_SIZE;
if (get_crypt_ftr_info(NULL, &off) == 0) {
ftr->persist_data_offset[0] = off + CRYPT_FOOTER_TO_PERSIST_OFFSET;
@@ -1614,7 +1720,7 @@
strcpy((char *)crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256");
/* Make an encrypted master key */
- if (create_encrypted_random_key(passwd, crypt_ftr.master_key, crypt_ftr.salt)) {
+ if (create_encrypted_random_key(passwd, crypt_ftr.master_key, crypt_ftr.salt, &crypt_ftr)) {
SLOGE("Cannot create encrypted master key\n");
goto error_unencrypted;
}
@@ -1636,7 +1742,7 @@
save_persistent_data();
}
- decrypt_master_key(passwd, crypt_ftr.salt, crypt_ftr.master_key, decrypted_master_key);
+ decrypt_master_key_and_upgrade(passwd, decrypted_master_key, &crypt_ftr);
create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev,
"userdata");
@@ -1784,7 +1890,7 @@
return -1;
}
- encrypt_master_key(newpw, crypt_ftr.salt, saved_master_key, crypt_ftr.master_key);
+ encrypt_master_key(newpw, crypt_ftr.salt, saved_master_key, crypt_ftr.master_key, &crypt_ftr);
/* save the key */
put_crypt_ftr_and_key(&crypt_ftr);
diff --git a/cryptfs.h b/cryptfs.h
index 4ac8a17..421181e 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -28,6 +28,10 @@
#include <cutils/properties.h>
+/* The current cryptfs version */
+#define CURRENT_MAJOR_VERSION 1
+#define CURRENT_MINOR_VERSION 2
+
#define CRYPT_FOOTER_OFFSET 0x4000
#define CRYPT_FOOTER_TO_PERSIST_OFFSET 0x1000
#define CRYPT_PERSIST_DATA_SIZE 0x1000
@@ -45,8 +49,16 @@
#define CRYPT_MNT_MAGIC 0xD0B5B1C4
#define PERSIST_DATA_MAGIC 0xE950CD44
+#define SCRYPT_PROP "ro.crypto.scrypt_params"
+#define SCRYPT_DEFAULTS { 15, 3, 1 }
+
+/* Key Derivation Function algorithms */
+#define KDF_PBKDF2 1
+#define KDF_SCRYPT 2
+
#define __le32 unsigned int
-#define __le16 unsigned short int
+#define __le16 unsigned short int
+#define __le8 unsigned char
struct crypt_mnt_ftr {
__le32 magic; /* See above */
@@ -71,6 +83,13 @@
__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) */
};
/* Persistant data that should be available before decryption.
@@ -114,6 +133,9 @@
#ifdef __cplusplus
extern "C" {
#endif
+
+ typedef void (*kdf_func)(char *passwd, unsigned char *salt, unsigned char *ikey, void *params);
+
int cryptfs_crypto_complete(void);
int cryptfs_check_passwd(char *pw);
int cryptfs_verify_passwd(char *newpw);