diff options
-rw-r--r-- | Android.mk | 16 | ||||
-rw-r--r-- | crypto/cryptfs/Android.mk | 53 | ||||
-rw-r--r-- | crypto/cryptfs/cryptfs.c | 74 | ||||
-rw-r--r-- | crypto/ics/cryptfs.c | 809 | ||||
-rw-r--r-- | crypto/ics/cryptfs.h | 44 | ||||
-rw-r--r-- | crypto/libcrypt_samsung/Android.mk | 11 | ||||
-rw-r--r-- | crypto/libcrypt_samsung/include/libcrypt_samsung.h | 141 | ||||
-rw-r--r-- | crypto/libcrypt_samsung/libcrypt_samsung.c | 68 | ||||
-rw-r--r-- | partitionmanager.cpp | 53 | ||||
-rw-r--r-- | prebuilt/Android.mk | 5 |
10 files changed, 613 insertions, 661 deletions
diff --git a/Android.mk b/Android.mk index 2f8c1942d..14ff6acbd 100644 --- a/Android.mk +++ b/Android.mk @@ -17,7 +17,6 @@ LOCAL_PATH := $(call my-dir) TARGET_RECOVERY_GUI := true include $(CLEAR_VARS) - LOCAL_SRC_FILES := \ recovery.cpp \ twbootloader.cpp \ @@ -193,6 +192,16 @@ ifeq ($(TW_INCLUDE_CRYPTO), true) LOCAL_CFLAGS += -DCRYPTO_FS_OPTIONS=\"$(TW_CRYPTO_FS_OPTIONS)\" LOCAL_CFLAGS += -DCRYPTO_FS_FLAGS=\"$(TW_CRYPTO_FS_FLAGS)\" LOCAL_CFLAGS += -DCRYPTO_KEY_LOC=\"$(TW_CRYPTO_KEY_LOC)\" +ifeq ($(TW_INCLUDE_CRYPTO_SAMSUNG), true) + LOCAL_CFLAGS += -DTW_INCLUDE_CRYPTO_SAMSUNG=\"$(TW_INCLUDE_CRYPTO_SAMSUNG)\" + ifdef TW_CRYPTO_SD_REAL_BLKDEV + LOCAL_CFLAGS += -DCRYPTO_SD_REAL_BLKDEV=\"$(TW_CRYPTO_SD_REAL_BLKDEV)\" + LOCAL_CFLAGS += -DCRYPTO_SD_FS_TYPE=\"$(TW_CRYPTO_SD_FS_TYPE)\" + endif + #LOCAL_LDFLAGS += -L$(TARGET_OUT_SHARED_LIBRARIES) -lsec_km + LOCAL_LDFLAGS += -ldl + LOCAL_STATIC_LIBRARIES += libcrypt_samsung +endif LOCAL_SHARED_LIBRARIES += libcrypto LOCAL_SRC_FILES += crypto/ics/cryptfs.c LOCAL_C_INCLUDES += system/extras/ext4_utils external/openssl/include @@ -265,13 +274,16 @@ include $(commands_recovery_local_path)/libjpegtwrp/Android.mk \ $(commands_recovery_local_path)/mtdutils/Android.mk \ $(commands_recovery_local_path)/pigz/Android.mk \ $(commands_recovery_local_path)/crypto/cryptsettings/Android.mk \ + $(commands_recovery_local_path)/crypto/cryptfs/Android.mk \ $(commands_recovery_local_path)/libcrecovery/Android.mk \ $(commands_recovery_local_path)/twmincrypt/Android.mk +ifeq ($(TW_INCLUDE_CRYPTO_SAMSUNG), true) + include $(commands_recovery_local_path)/crypto/libcrypt_samsung/Android.mk +endif ifeq ($(TW_INCLUDE_JB_CRYPTO), true) include $(commands_recovery_local_path)/crypto/fs_mgr/Android.mk endif commands_recovery_local_path := - diff --git a/crypto/cryptfs/Android.mk b/crypto/cryptfs/Android.mk new file mode 100644 index 000000000..3267c931d --- /dev/null +++ b/crypto/cryptfs/Android.mk @@ -0,0 +1,53 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + cryptfs.c + +LOCAL_CFLAGS:= -g -c -W -I../fs_mgr/include +LOCAL_CFLAGS += -DTW_INCLUDE_CRYPTO +LOCAL_CFLAGS += -DCRYPTO_FS_TYPE=\"$(TW_CRYPTO_FS_TYPE)\" +LOCAL_CFLAGS += -DCRYPTO_REAL_BLKDEV=\"$(TW_CRYPTO_REAL_BLKDEV)\" +LOCAL_CFLAGS += -DCRYPTO_MNT_POINT=\"$(TW_CRYPTO_MNT_POINT)\" +LOCAL_CFLAGS += -DCRYPTO_FS_OPTIONS=\"$(TW_CRYPTO_FS_OPTIONS)\" +LOCAL_CFLAGS += -DCRYPTO_FS_FLAGS=\"$(TW_CRYPTO_FS_FLAGS)\" +LOCAL_CFLAGS += -DCRYPTO_KEY_LOC=\"$(TW_CRYPTO_KEY_LOC)\" +ifdef TW_CRYPTO_SD_REAL_BLKDEV + LOCAL_CFLAGS += -DCRYPTO_SD_REAL_BLKDEV=\"$(TW_CRYPTO_SD_REAL_BLKDEV)\" + LOCAL_CFLAGS += -DCRYPTO_SD_FS_TYPE=\"$(TW_CRYPTO_SD_FS_TYPE)\" +endif +ifneq ($(TW_INTERNAL_STORAGE_PATH),) + LOCAL_CFLAGS += -DTW_INTERNAL_STORAGE_PATH=$(TW_INTERNAL_STORAGE_PATH) +endif +ifneq ($(TW_INTERNAL_STORAGE_MOUNT_POINT),) + LOCAL_CFLAGS += -DTW_INTERNAL_STORAGE_MOUNT_POINT=$(TW_INTERNAL_STORAGE_MOUNT_POINT) +endif +ifneq ($(TW_EXTERNAL_STORAGE_PATH),) + LOCAL_CFLAGS += -DTW_EXTERNAL_STORAGE_PATH=$(TW_EXTERNAL_STORAGE_PATH) +endif +ifneq ($(TW_EXTERNAL_STORAGE_MOUNT_POINT),) + LOCAL_CFLAGS += -DTW_EXTERNAL_STORAGE_MOUNT_POINT=$(TW_EXTERNAL_STORAGE_MOUNT_POINT) +endif + +LOCAL_C_INCLUDES += system/extras/ext4_utils external/openssl/include +LOCAL_MODULE:=cryptfs +LOCAL_MODULE_TAGS:= eng +LOCAL_SHARED_LIBRARIES += libc libcutils +LOCAL_SHARED_LIBRARIES += libcrypto + + +#LOCAL_LDFLAGS += -L$(TARGET_OUT_SHARED_LIBRARIES) -lsec_km -lsec_ecryptfs -ldl +LOCAL_LDFLAGS += -ldl + +LOCAL_STATIC_LIBRARIES += libmtdutils +LOCAL_STATIC_LIBRARIES += libminadbd libminzip libunz +LOCAL_STATIC_LIBRARIES += libminuitwrp libpixelflinger_static libpng libjpegtwrp libgui +LOCAL_SHARED_LIBRARIES += libz libc libstlport libcutils libstdc++ libmincrypt libext4_utils +LOCAL_STATIC_LIBRARIES += libcrypt_samsung + + +LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB) +#LOCAL_STATIC_LIBRARIES += libfs_mgrtwrp +LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities +include $(BUILD_EXECUTABLE) diff --git a/crypto/cryptfs/cryptfs.c b/crypto/cryptfs/cryptfs.c new file mode 100644 index 000000000..59e7added --- /dev/null +++ b/crypto/cryptfs/cryptfs.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013 a3955269 all rights reversed, no rights reserved. + */ + +#define TW_INCLUDE_CRYPTO_SAMSUNG +#include "../ics/cryptfs.c" + +int dm_remove_device(const char *name) +{ + int r; + r = delete_crypto_blk_dev(name); + if(!r) + printf("crypto block device '%s' deleted.\n", name); + else + printf("deleting crypto block device '%s' failed. [%d - %s]\n", name, r, strerror(errno)); + return r; +} + +int ecryptfs_test(const char *pw) +{ + char pwbuf[256]; + int r; + + strcpy(pwbuf, pw); + // 0: building options without file encryption filtering. + // 1: building options with media files filtering. + // 2: building options with all new files filtering. + r = mount_ecryptfs_drive(pwbuf, "/emmc", "/emmc", 0); + printf("mount_ecryptfs_drive: %d\n", r); + r = mount("/dev/block/mmcblk1", "/emmc", "vfat", MS_RDONLY, ""); + printf("mount: %d\n", r); + + r = umount("/emmc");///dev/block/mmcblk1"); + printf("umount: %d\n", r); + + //r = unmount_ecryptfs_drive("/emmc"); + //printf("unmount_ecryptfs_drive: %d\n", r); + + return r; +} + +int main(int argc, char* argv[]) +{ + if(argc < 2) + { + printf("no args!\n"); + return 1; + } + + property_set("ro.crypto.state", "encrypted"); + + property_set("ro.crypto.fs_type", CRYPTO_FS_TYPE); + property_set("ro.crypto.fs_real_blkdev", CRYPTO_REAL_BLKDEV); + property_set("ro.crypto.fs_mnt_point", CRYPTO_MNT_POINT); + property_set("ro.crypto.fs_options", CRYPTO_FS_OPTIONS); + property_set("ro.crypto.fs_flags", CRYPTO_FS_FLAGS); + property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC); + +#ifdef CRYPTO_SD_FS_TYPE + property_set("ro.crypto.sd_fs_type", CRYPTO_SD_FS_TYPE); + property_set("ro.crypto.sd_fs_real_blkdev", CRYPTO_SD_REAL_BLKDEV); + property_set("ro.crypto.sd_fs_mnt_point", EXPAND(TW_INTERNAL_STORAGE_PATH)); +#endif + + property_set("rw.km_fips_status", "ready"); + + delete_crypto_blk_dev("userdata"); + delete_crypto_blk_dev("sdcard"); + delete_crypto_blk_dev("emmc"); + + cryptfs_check_passwd(argv[1]); + + return 0; +}; diff --git a/crypto/ics/cryptfs.c b/crypto/ics/cryptfs.c index 5751cf74d..8a6c581fe 100644 --- a/crypto/ics/cryptfs.c +++ b/crypto/ics/cryptfs.c @@ -49,6 +49,9 @@ #define DATA_MNT_POINT "/data" #define HASH_COUNT 2000 +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG +#define KEY_LEN_BYTES_SAMSUNG (sizeof(edk_t)) +#endif #define KEY_LEN_BYTES 16 #define IV_LEN_BYTES 16 @@ -58,12 +61,26 @@ #define EXT4_FS 1 #define FAT_FS 2 +#ifndef EXPAND +#define STRINGIFY(x) #x +#define EXPAND(x) STRINGIFY(x) +#endif + char *me = "cryptfs"; -static unsigned char saved_master_key[KEY_LEN_BYTES]; static char *saved_data_blkdev; static char *saved_mount_point; static int master_key_saved = 0; +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG +static int using_samsung_encryption = 0; +//static edk_t saved_master_key; +static unsigned char saved_master_key[KEY_LEN_BYTES_SAMSUNG]; +#else +static unsigned char saved_master_key[KEY_LEN_BYTES]; +#endif + +int cryptfs_setup_volume(const char *label, const char *real_blkdev, char *crypto_blkdev); + static void ioctl_init(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags) { @@ -79,37 +96,6 @@ static void ioctl_init(struct dm_ioctl *io, size_t dataSize, const char *name, u } } -static unsigned int get_fs_size(char *dev) -{ - int fd, block_size; - struct ext4_super_block sb; - off64_t len; - - if ((fd = open(dev, O_RDONLY)) < 0) { - SLOGE("Cannot open device to get filesystem size "); - return 0; - } - - if (lseek64(fd, 1024, SEEK_SET) < 0) { - SLOGE("Cannot seek to superblock"); - return 0; - } - - if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) { - SLOGE("Cannot read superblock"); - return 0; - } - - close(fd); - - block_size = 1024 << sb.s_log_block_size; - /* compute length in bytes */ - len = ( ((off64_t)sb.s_blocks_count_hi << 32) + sb.s_blocks_count_lo) * block_size; - - /* return length in sectors */ - return (unsigned int) (len / 512); -} - static unsigned int get_blkdev_size(int fd) { unsigned int nr_sec; @@ -127,100 +113,8 @@ static unsigned int get_blkdev_size(int fd) static int put_crypt_ftr_and_key(char *real_blk_name, struct crypt_mnt_ftr *crypt_ftr, unsigned char *key, unsigned char *salt) { - int fd; - unsigned int nr_sec, cnt; - off64_t off; - int rc = -1; - char *fname; - char key_loc[PROPERTY_VALUE_MAX]; - struct stat statbuf; - - property_get(KEY_LOC_PROP, key_loc, KEY_IN_FOOTER); - - if (!strcmp(key_loc, KEY_IN_FOOTER)) { - fname = real_blk_name; - if ( (fd = open(fname, O_RDWR)) < 0) { - SLOGE("Cannot open real block device %s\n", fname); - return -1; - } - - if ( (nr_sec = get_blkdev_size(fd)) == 0) { - SLOGE("Cannot get size of block device %s\n", fname); - goto errout; - } - - /* If it's an encrypted Android partition, the last 16 Kbytes contain the - * encryption info footer and key, and plenty of bytes to spare for future - * growth. - */ - off = ((off64_t)nr_sec * 512) - CRYPT_FOOTER_OFFSET; - - if (lseek64(fd, off, SEEK_SET) == -1) { - SLOGE("Cannot seek to real block device footer\n"); - goto errout; - } - } else if (key_loc[0] == '/') { - fname = key_loc; - if ( (fd = open(fname, O_RDWR | O_CREAT, 0600)) < 0) { - SLOGE("Cannot open footer file %s\n", fname); - return -1; - } - } else { - SLOGE("Unexpected value for" KEY_LOC_PROP "\n"); - return -1;; - } - - if ((cnt = write(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr))) != sizeof(struct crypt_mnt_ftr)) { - SLOGE("Cannot write real block device footer\n"); - goto errout; - } - - if (key) { - if (crypt_ftr->keysize != KEY_LEN_BYTES) { - SLOGE("Keysize of %d bits not supported for real block device %s\n", - crypt_ftr->keysize*8, fname); - goto errout; - } - - if ( (cnt = write(fd, key, crypt_ftr->keysize)) != crypt_ftr->keysize) { - SLOGE("Cannot write key for real block device %s\n", fname); - goto errout; - } - } - - if (salt) { - /* Compute the offset from the last write to the salt */ - off = KEY_TO_SALT_PADDING; - if (! key) - off += crypt_ftr->keysize; - - if (lseek64(fd, off, SEEK_CUR) == -1) { - SLOGE("Cannot seek to real block device salt \n"); - goto errout; - } - - if ( (cnt = write(fd, salt, SALT_LEN)) != SALT_LEN) { - SLOGE("Cannot write salt for real block device %s\n", fname); - goto errout; - } - } - - fstat(fd, &statbuf); - /* If the keys are kept on a raw block device, do not try to truncate it. */ - if (S_ISREG(statbuf.st_mode) && (key_loc[0] == '/')) { - if (ftruncate(fd, 0x4000)) { - SLOGE("Cannot set footer file size\n", fname); - goto errout; - } - } - - /* Success! */ - rc = 0; - -errout: - close(fd); - return rc; - + // we don't need to update it... + return 0; } static int get_crypt_ftr_and_key(char *real_blk_name, struct crypt_mnt_ftr *crypt_ftr, @@ -267,7 +161,11 @@ static int get_crypt_ftr_and_key(char *real_blk_name, struct crypt_mnt_ftr *cryp /* Make sure it's 16 Kbytes in length */ fstat(fd, &statbuf); - if (S_ISREG(statbuf.st_mode) && (statbuf.st_size != 0x4000)) { + if (S_ISREG(statbuf.st_mode) && (statbuf.st_size != 0x4000 +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG + && statbuf.st_size != 0x8000 +#endif + )) { printf("footer file %s is not the expected size!\n", fname); goto errout; } @@ -282,8 +180,20 @@ static int get_crypt_ftr_and_key(char *real_blk_name, struct crypt_mnt_ftr *cryp } if (crypt_ftr->magic != CRYPT_MNT_MAGIC) { +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG + if (crypt_ftr->magic != CRYPT_MNT_MAGIC_SAMSUNG) { + printf("Bad magic for real block device %s\n", fname); + goto errout; + } else { + printf("Using Samsung encryption.\n"); + using_samsung_encryption = 1; + memcpy(key, &crypt_ftr->edk_payload, sizeof(edk_payload_t)); + + } +#else printf("Bad magic for real block device %s\n", fname); goto errout; +#endif } if (crypt_ftr->major_version != 1) { @@ -307,7 +217,7 @@ static int get_crypt_ftr_and_key(char *real_blk_name, struct crypt_mnt_ftr *cryp } } - if (crypt_ftr->keysize != KEY_LEN_BYTES) { + if (crypt_ftr->keysize != sizeof(saved_master_key)) { printf("Keysize of %d bits not supported for real block device %s\n", crypt_ftr->keysize * 8, fname); goto errout; @@ -360,7 +270,7 @@ void convert_key_to_hex_ascii(unsigned char *master_key, unsigned int keysize, } static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key, - char *real_blk_name, char *crypto_blk_name, const char *name) + const char *real_blk_name, char *crypto_blk_name, const char *name) { char buffer[DM_CRYPT_BUF_SIZE]; char master_key_ascii[129]; /* Large enough to hold 512 bit key and null */ @@ -407,6 +317,7 @@ static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr, unsigned char convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii); sprintf(crypt_params, "%s %s 0 %s 0", crypt_ftr->crypto_type_name, master_key_ascii, real_blk_name); + //printf("cryptsetup params: '%s'\n", crypt_params); crypt_params += strlen(crypt_params) + 1; crypt_params = (char *) (((unsigned long)crypt_params + 7) & ~8); /* Align to an 8 byte boundary */ tgt->next = crypt_params - buffer; @@ -433,7 +344,7 @@ errout: return retval; } -static int delete_crypto_blk_dev(char *name) +static int delete_crypto_blk_dev(const char *name) { int fd; char buffer[DM_CRYPT_BUF_SIZE]; @@ -470,47 +381,17 @@ static void pbkdf2(char *passwd, unsigned char *salt, unsigned char *ikey) HASH_COUNT, KEY_LEN_BYTES+IV_LEN_BYTES, ikey); } -static int encrypt_master_key(char *passwd, unsigned char *salt, - unsigned char *decrypted_master_key, - unsigned char *encrypted_master_key) -{ - 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); - - /* Initialize the decryption engine */ - if (! EVP_EncryptInit(&e_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) { - SLOGE("EVP_EncryptInit failed\n"); - return -1; - } - EVP_CIPHER_CTX_set_padding(&e_ctx, 0); /* Turn off padding as our data is block aligned */ - - /* Encrypt the master key */ - if (! EVP_EncryptUpdate(&e_ctx, encrypted_master_key, &encrypted_len, - decrypted_master_key, KEY_LEN_BYTES)) { - SLOGE("EVP_EncryptUpdate failed\n"); - return -1; - } - if (! EVP_EncryptFinal(&e_ctx, encrypted_master_key + encrypted_len, &final_len)) { - SLOGE("EVP_EncryptFinal failed\n"); - return -1; - } - - if (encrypted_len + final_len != KEY_LEN_BYTES) { - SLOGE("EVP_Encryption length check failed with %d, %d bytes\n", encrypted_len, final_len); - return -1; - } else { - return 0; - } -} - static int decrypt_master_key(char *passwd, unsigned char *salt, unsigned char *encrypted_master_key, unsigned char *decrypted_master_key) { +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG + if (using_samsung_encryption) { + property_set("rw.km_fips_status", "ready"); + return decrypt_EDK((dek_t*)decrypted_master_key, (edk_payload_t*)encrypted_master_key, passwd); + } +#endif + 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; @@ -539,25 +420,9 @@ static int decrypt_master_key(char *passwd, unsigned char *salt, } } -static int create_encrypted_random_key(char *passwd, unsigned char *master_key, unsigned char *salt) -{ - int fd; - unsigned char key_buf[KEY_LEN_BYTES]; - EVP_CIPHER_CTX e_ctx; - int encrypted_len, final_len; - - /* Get some random bits for a key */ - fd = open("/dev/urandom", O_RDONLY); - read(fd, key_buf, sizeof(key_buf)); - read(fd, salt, SALT_LEN); - close(fd); - - /* Now encrypt it with the password */ - return encrypt_master_key(passwd, salt, key_buf, master_key); -} - -static int get_orig_mount_parms(char *mount_point, char *fs_type, char *real_blkdev, - unsigned long *mnt_flags, char *fs_options) +static int get_orig_mount_parms( + const char *mount_point, char *fs_type, char *real_blkdev, + unsigned long *mnt_flags, char *fs_options) { char mount_point2[PROPERTY_VALUE_MAX]; char fs_flags[PROPERTY_VALUE_MAX]; @@ -577,197 +442,34 @@ static int get_orig_mount_parms(char *mount_point, char *fs_type, char *real_blk return 0; } -static int wait_and_unmount(char *mountpoint) -{ - int i, rc; -#define WAIT_UNMOUNT_COUNT 20 - - /* Now umount the tmpfs filesystem */ - for (i=0; i<WAIT_UNMOUNT_COUNT; i++) { - if (umount(mountpoint)) { - if (errno == EINVAL) { - /* EINVAL is returned if the directory is not a mountpoint, - * i.e. there is no filesystem mounted there. So just get out. - */ - break; - } - sleep(1); - i++; - } else { - break; - } - } - - if (i < WAIT_UNMOUNT_COUNT) { - SLOGD("unmounting %s succeeded\n", mountpoint); - rc = 0; - } else { - SLOGE("unmounting %s failed\n", mountpoint); - rc = -1; - } - - return rc; -} - -#define DATA_PREP_TIMEOUT 100 -static int prep_data_fs(void) +static int get_orig_mount_parms_sd( + const char *mount_point, char *fs_type, char *real_blkdev) { - int i; - - /* Do the prep of the /data filesystem */ - property_set("vold.post_fs_data_done", "0"); - property_set("vold.decrypt", "trigger_post_fs_data"); - SLOGD("Just triggered post_fs_data\n"); - - /* Wait a max of 25 seconds, hopefully it takes much less */ - for (i=0; i<DATA_PREP_TIMEOUT; i++) { - char p[PROPERTY_VALUE_MAX]; - - property_get("vold.post_fs_data_done", p, "0"); - if (*p == '1') { - break; - } else { - usleep(250000); - } - } - if (i == DATA_PREP_TIMEOUT) { - /* Ugh, we failed to prep /data in time. Bail. */ - return -1; - } else { - SLOGD("post_fs_data done\n"); - return 0; - } -} - -int cryptfs_restart(void) -{ - char fs_type[32]; - char real_blkdev[MAXPATHLEN]; - char crypto_blkdev[MAXPATHLEN]; - char fs_options[256]; - unsigned long mnt_flags; - struct stat statbuf; - int rc = -1, i; - static int restart_successful = 0; - - /* Validate that it's OK to call this routine */ - if (! master_key_saved) { - SLOGE("Encrypted filesystem not validated, aborting"); - return -1; - } - - if (restart_successful) { - SLOGE("System already restarted with encrypted disk, aborting"); - return -1; - } - - /* Here is where we shut down the framework. The init scripts - * start all services in one of three classes: core, main or late_start. - * On boot, we start core and main. Now, we stop main, but not core, - * as core includes vold and a few other really important things that - * we need to keep running. Once main has stopped, we should be able - * to umount the tmpfs /data, then mount the encrypted /data. - * We then restart the class main, and also the class late_start. - * At the moment, I've only put a few things in late_start that I know - * are not needed to bring up the framework, and that also cause problems - * with unmounting the tmpfs /data, but I hope to add add more services - * to the late_start class as we optimize this to decrease the delay - * till the user is asked for the password to the filesystem. - */ + char mount_point2[PROPERTY_VALUE_MAX]; - /* The init files are setup to stop the class main when vold.decrypt is - * set to trigger_reset_main. - */ - property_set("vold.decrypt", "trigger_reset_main"); - SLOGD("Just asked init to shut down class main\n"); + property_get("ro.crypto.sd_fs_type", fs_type, ""); + property_get("ro.crypto.sd_fs_real_blkdev", real_blkdev, ""); + property_get("ro.crypto.sd_fs_mnt_point", mount_point2, ""); - /* Now that the framework is shutdown, we should be able to umount() - * the tmpfs filesystem, and mount the real one. - */ - - property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, ""); - if (strlen(crypto_blkdev) == 0) { - SLOGE("fs_crypto_blkdev not set\n"); + if (strcmp(mount_point, mount_point2)) { + /* Consistency check. These should match. If not, something odd happened. */ return -1; } - if (! get_orig_mount_parms(DATA_MNT_POINT, fs_type, real_blkdev, &mnt_flags, fs_options)) { - SLOGD("Just got orig mount parms\n"); - - if (! (rc = wait_and_unmount(DATA_MNT_POINT)) ) { - /* If that succeeded, then mount the decrypted filesystem */ - mount(crypto_blkdev, DATA_MNT_POINT, fs_type, mnt_flags, fs_options); - - property_set("vold.decrypt", "trigger_load_persist_props"); - /* Create necessary paths on /data */ - if (prep_data_fs()) { - return -1; - } - - /* startup service classes main and late_start */ - property_set("vold.decrypt", "trigger_restart_framework"); - SLOGD("Just triggered restart_framework\n"); - - /* Give it a few moments to get started */ - sleep(1); - } - } - - if (rc == 0) { - restart_successful = 1; - } - - return rc; -} - -static int do_crypto_complete(char *mount_point) -{ - struct crypt_mnt_ftr crypt_ftr; - unsigned char encrypted_master_key[32]; - unsigned char salt[SALT_LEN]; - char real_blkdev[MAXPATHLEN]; - char fs_type[PROPERTY_VALUE_MAX]; - char fs_options[PROPERTY_VALUE_MAX]; - unsigned long mnt_flags; - char encrypted_state[PROPERTY_VALUE_MAX]; - - property_get("ro.crypto.state", encrypted_state, ""); - if (strcmp(encrypted_state, "encrypted") ) { - SLOGE("not running with encryption, aborting"); - return 1; - } - - if (get_orig_mount_parms(mount_point, fs_type, real_blkdev, &mnt_flags, fs_options)) { - SLOGE("Error reading original mount parms for mount point %s\n", mount_point); - return -1; - } - - if (get_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt)) { - SLOGE("Error getting crypt footer and key\n"); - return -1; - } - - if (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS) { - SLOGE("Encryption process didn't finish successfully\n"); - return -2; /* -2 is the clue to the UI that there is no usable data on the disk, - * and give the user an option to wipe the disk */ - } - - /* We passed the test! We shall diminish, and return to the west */ - return 0; + return 0; } -static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) +static int test_mount_encrypted_fs( + char *passwd, char *mount_point, char *label, char *crypto_blkdev) { struct crypt_mnt_ftr crypt_ftr; /* Allocate enough space for a 256 bit key, but we may use less */ - unsigned char encrypted_master_key[32], decrypted_master_key[32]; + unsigned char encrypted_master_key[256], decrypted_master_key[32]; unsigned char salt[SALT_LEN]; - char crypto_blkdev[MAXPATHLEN]; char real_blkdev[MAXPATHLEN]; char fs_type[PROPERTY_VALUE_MAX]; char fs_options[PROPERTY_VALUE_MAX]; - char tmp_mount_point[64]; + char tmp_mount_point[MAXPATHLEN]; unsigned long mnt_flags; unsigned int orig_failed_decrypt_count; char encrypted_state[PROPERTY_VALUE_MAX]; @@ -775,7 +477,7 @@ static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) property_get("ro.crypto.state", encrypted_state, ""); if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) { - printf("encrypted fs already validated or not running with encryption, aborting"); + printf("encrypted fs already validated or not running with encryption, aborting %s\n", encrypted_state); return -1; } @@ -789,15 +491,15 @@ static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) return -1; } - printf("crypt_ftr->fs_size = %lld\n", crypt_ftr.fs_size); + //printf("crypt_ftr->fs_size = %lld\n", crypt_ftr.fs_size); orig_failed_decrypt_count = crypt_ftr.failed_decrypt_count; if (! (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) ) { decrypt_master_key(passwd, salt, encrypted_master_key, decrypted_master_key); } - if (create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, - real_blkdev, crypto_blkdev, label)) { + if (create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, + crypto_blkdev, label)) { printf("Error creating decrypted block device\n"); return -1; } @@ -811,7 +513,7 @@ static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) */ sprintf(tmp_mount_point, "%s/tmp_mnt", mount_point); mkdir(tmp_mount_point, 0755); - if ( mount(crypto_blkdev, tmp_mount_point, "ext4", MS_RDONLY, "") ) { + if ( mount(crypto_blkdev, tmp_mount_point, fs_type, MS_RDONLY, "") ) { printf("Error temp mounting decrypted block device\n"); delete_crypto_blk_dev(label); crypt_ftr.failed_decrypt_count++; @@ -823,9 +525,7 @@ static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) crypt_ftr.failed_decrypt_count = 0; } - if (orig_failed_decrypt_count != crypt_ftr.failed_decrypt_count) { - put_crypt_ftr_and_key(real_blkdev, &crypt_ftr, 0, 0); - } + rmdir(tmp_mount_point); if (crypt_ftr.failed_decrypt_count) { /* We failed to mount the device, so return an error */ @@ -840,7 +540,7 @@ static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) /* Also save a the master key so we can reencrypted the key * the key when we want to change the password on it. */ - memcpy(saved_master_key, decrypted_master_key, KEY_LEN_BYTES); + memcpy(saved_master_key, decrypted_master_key, sizeof(saved_master_key)); saved_data_blkdev = strdup(real_blkdev); saved_mount_point = strdup(mount_point); master_key_saved = 1; @@ -850,315 +550,152 @@ static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) return rc; } -/* Called by vold when it wants to undo the crypto mapping of a volume it - * manages. This is usually in response to a factory reset, when we want - * to undo the crypto mapping so the volume is formatted in the clear. - */ -int cryptfs_revert_volume(const char *label) +static int test_mount_encrypted_fs_sd( + const char *passwd, const char *mount_point, const char *label) { - return delete_crypto_blk_dev((char *)label); -} - -/* - * Called by vold when it's asked to mount an encrypted, nonremovable volume. - * Setup a dm-crypt mapping, use the saved master key from - * setting up the /data mapping, and return the new device path. - */ -int cryptfs_setup_volume(const char *label, int major, int minor, - char *crypto_sys_path, unsigned int max_path, - int *new_major, int *new_minor) -{ - char real_blkdev[MAXPATHLEN], crypto_blkdev[MAXPATHLEN]; - struct crypt_mnt_ftr sd_crypt_ftr; - unsigned char key[32], salt[32]; - struct stat statbuf; - int nr_sec, fd; - - sprintf(real_blkdev, "/dev/block/vold/%d:%d", major, minor); - - /* Just want the footer, but gotta get it all */ - get_crypt_ftr_and_key(saved_data_blkdev, &sd_crypt_ftr, key, salt); - - /* Update the fs_size field to be the size of the volume */ - fd = open(real_blkdev, O_RDONLY); - nr_sec = get_blkdev_size(fd); - close(fd); - if (nr_sec == 0) { - SLOGE("Cannot get size of volume %s\n", real_blkdev); - return -1; - } - - sd_crypt_ftr.fs_size = nr_sec; - create_crypto_blk_dev(&sd_crypt_ftr, saved_master_key, real_blkdev, - crypto_blkdev, label); - - stat(crypto_blkdev, &statbuf); - *new_major = MAJOR(statbuf.st_rdev); - *new_minor = MINOR(statbuf.st_rdev); - - /* Create path to sys entry for this block device */ - snprintf(crypto_sys_path, max_path, "/devices/virtual/block/%s", strrchr(crypto_blkdev, '/')+1); - - return 0; -} - -int cryptfs_crypto_complete(void) -{ - return do_crypto_complete("/data"); -} - -int cryptfs_check_passwd(char *passwd) -{ - int rc = -1; - - rc = test_mount_encrypted_fs(passwd, DATA_MNT_POINT, "userdata"); - - return rc; -} - -int cryptfs_verify_passwd(char *passwd) -{ - struct crypt_mnt_ftr crypt_ftr; - /* Allocate enough space for a 256 bit key, but we may use less */ - unsigned char encrypted_master_key[32], decrypted_master_key[32]; - unsigned char salt[SALT_LEN]; char real_blkdev[MAXPATHLEN]; - char fs_type[PROPERTY_VALUE_MAX]; - char fs_options[PROPERTY_VALUE_MAX]; - unsigned long mnt_flags; + char crypto_blkdev[MAXPATHLEN]; + char tmp_mount_point[MAXPATHLEN]; char encrypted_state[PROPERTY_VALUE_MAX]; + char fs_type[PROPERTY_VALUE_MAX]; int rc; property_get("ro.crypto.state", encrypted_state, ""); - if (strcmp(encrypted_state, "encrypted") ) { - SLOGE("device not encrypted, aborting"); - return -2; - } - - if (!master_key_saved) { - SLOGE("encrypted fs not yet mounted, aborting"); + if ( !master_key_saved || strcmp(encrypted_state, "encrypted") ) { + printf("encrypted fs not yet validated or not running with encryption, aborting\n"); return -1; } - if (!saved_mount_point) { - SLOGE("encrypted fs failed to save mount point, aborting"); + if (get_orig_mount_parms_sd(mount_point, fs_type, real_blkdev)) { + printf("Error reading original mount parms for mount point %s\n", mount_point); return -1; } - if (get_orig_mount_parms(saved_mount_point, fs_type, real_blkdev, &mnt_flags, fs_options)) { - SLOGE("Error reading original mount parms for mount point %s\n", saved_mount_point); + rc = cryptfs_setup_volume(label, real_blkdev, crypto_blkdev); + if(rc){ + printf("Error setting up cryptfs volume %s\n", real_blkdev); return -1; } - if (get_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt)) { - SLOGE("Error getting crypt footer and key\n"); - return -1; - } - - if (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) { - /* If the device has no password, then just say the password is valid */ - rc = 0; + sprintf(tmp_mount_point, "%s/tmp_mnt", mount_point); + mkdir(tmp_mount_point, 0755); + if ( mount(crypto_blkdev, tmp_mount_point, fs_type, MS_RDONLY, "") ) { + printf("Error temp mounting decrypted block device\n"); + delete_crypto_blk_dev(label); } else { - decrypt_master_key(passwd, salt, encrypted_master_key, decrypted_master_key); - if (!memcmp(decrypted_master_key, saved_master_key, crypt_ftr.keysize)) { - /* They match, the password is correct */ - rc = 0; - } else { - /* If incorrect, sleep for a bit to prevent dictionary attacks */ - sleep(1); - rc = 1; - } - } + /* Success, so just umount and we'll mount it properly when we restart + * the framework. + */ + umount(tmp_mount_point); - return rc; -} - -/* Initialize a crypt_mnt_ftr structure. The keysize is - * defaulted to 16 bytes, and the filesystem size to 0. - * Presumably, at a minimum, the caller will update the - * filesystem size and crypto_type_name after calling this function. - */ -static void cryptfs_init_crypt_mnt_ftr(struct crypt_mnt_ftr *ftr) -{ - ftr->magic = CRYPT_MNT_MAGIC; - ftr->major_version = 1; - ftr->minor_version = 0; - ftr->ftr_size = sizeof(struct crypt_mnt_ftr); - ftr->flags = 0; - ftr->keysize = KEY_LEN_BYTES; - ftr->spare1 = 0; - ftr->fs_size = 0; - ftr->failed_decrypt_count = 0; - ftr->crypto_type_name[0] = '\0'; -} - -static int cryptfs_enable_wipe(char *crypto_blkdev, off64_t size, int type) -{ - char cmdline[256]; - int rc = -1; - - if (type == EXT4_FS) { - snprintf(cmdline, sizeof(cmdline), "/system/bin/make_ext4fs -a /data -l %lld %s", - size * 512, crypto_blkdev); - SLOGI("Making empty filesystem with command %s\n", cmdline); - } else if (type== FAT_FS) { - snprintf(cmdline, sizeof(cmdline), "/system/bin/newfs_msdos -F 32 -O android -c 8 -s %lld %s", - size, crypto_blkdev); - SLOGI("Making empty filesystem with command %s\n", cmdline); - } else { - SLOGE("cryptfs_enable_wipe(): unknown filesystem type %d\n", type); - return -1; + property_set("ro.crypto.sd_fs_crypto_blkdev", crypto_blkdev); } - if (system(cmdline)) { - SLOGE("Error creating empty filesystem on %s\n", crypto_blkdev); - } else { - SLOGD("Successfully created empty filesystem on %s\n", crypto_blkdev); - rc = 0; - } + rmdir(tmp_mount_point); return rc; } -static inline int unix_read(int fd, void* buff, int len) -{ - int ret; - do { ret = read(fd, buff, len); } while (ret < 0 && errno == EINTR); - return ret; -} - -static inline int unix_write(int fd, const void* buff, int len) -{ - int ret; - do { ret = write(fd, buff, len); } while (ret < 0 && errno == EINTR); - return ret; -} - -#define CRYPT_INPLACE_BUFSIZE 4096 -#define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / 512) -static int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev, off64_t size, - off64_t *size_already_done, off64_t tot_size) +/* + * Called by vold when it's asked to mount an encrypted, nonremovable volume. + * Setup a dm-crypt mapping, use the saved master key from + * setting up the /data mapping, and return the new device path. + */ +int cryptfs_setup_volume(const char *label, const char *real_blkdev, char *crypto_blkdev) { - int realfd, cryptofd; - char *buf[CRYPT_INPLACE_BUFSIZE]; - int rc = -1; - off64_t numblocks, i, remainder; - off64_t one_pct, cur_pct, new_pct; - off64_t blocks_already_done, tot_numblocks; + struct crypt_mnt_ftr sd_crypt_ftr; + unsigned char key[256], salt[32]; + struct stat statbuf; + int nr_sec, fd, rc; - if ( (realfd = open(real_blkdev, O_RDONLY)) < 0) { - SLOGE("Error opening real_blkdev %s for inplace encrypt\n", real_blkdev); - return -1; - } + /* Just want the footer, but gotta get it all */ + get_crypt_ftr_and_key(saved_data_blkdev, &sd_crypt_ftr, key, salt); - if ( (cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) { - SLOGE("Error opening crypto_blkdev %s for inplace encrypt\n", crypto_blkdev); - close(realfd); + /* Update the fs_size field to be the size of the volume */ + fd = open(real_blkdev, O_RDONLY); + nr_sec = get_blkdev_size(fd); + close(fd); + if (nr_sec == 0) { + SLOGE("Cannot get size of volume %s\n", real_blkdev); return -1; } - /* This is pretty much a simple loop of reading 4K, and writing 4K. - * The size passed in is the number of 512 byte sectors in the filesystem. - * So compute the number of whole 4K blocks we should read/write, - * and the remainder. - */ - numblocks = size / CRYPT_SECTORS_PER_BUFSIZE; - remainder = size % CRYPT_SECTORS_PER_BUFSIZE; - tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE; - blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE; - - SLOGE("Encrypting filesystem in place..."); - - one_pct = tot_numblocks / 100; - cur_pct = 0; - /* process the majority of the filesystem in blocks */ - for (i=0; i<numblocks; i++) { - new_pct = (i + blocks_already_done) / one_pct; - if (new_pct > cur_pct) { - char buf[8]; - - cur_pct = new_pct; - snprintf(buf, sizeof(buf), "%lld", cur_pct); - property_set("vold.encrypt_progress", buf); - } - if (unix_read(realfd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) { - SLOGE("Error reading real_blkdev %s for inplace encrypt\n", crypto_blkdev); - goto errout; +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG + if(using_samsung_encryption) { + if(!access("/efs/essiv", R_OK)){ + strcpy(sd_crypt_ftr.crypto_type_name, "aes-cbc-plain:sha1"); } - if (unix_write(cryptofd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) { - SLOGE("Error writing crypto_blkdev %s for inplace encrypt\n", crypto_blkdev); - goto errout; + else if(!access("/efs/cryptprop_essiv", R_OK)){ + strcpy(sd_crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256"); } } +#endif - /* Do any remaining sectors */ - for (i=0; i<remainder; i++) { - if (unix_read(realfd, buf, 512) <= 0) { - SLOGE("Error reading rival sectors from real_blkdev %s for inplace encrypt\n", crypto_blkdev); - goto errout; - } - if (unix_write(cryptofd, buf, 512) <= 0) { - SLOGE("Error writing final sectors to crypto_blkdev %s for inplace encrypt\n", crypto_blkdev); - goto errout; - } - } - - *size_already_done += size; - rc = 0; + sd_crypt_ftr.fs_size = nr_sec; + rc = create_crypto_blk_dev( + &sd_crypt_ftr, saved_master_key, real_blkdev, crypto_blkdev, label); -errout: - close(realfd); - close(cryptofd); + stat(crypto_blkdev, &statbuf); return rc; } -#define CRYPTO_ENABLE_WIPE 1 -#define CRYPTO_ENABLE_INPLACE 2 - -#define FRAMEWORK_BOOT_WAIT 60 - -static inline int should_encrypt(struct volume_info *volume) -{ - return (volume->flags & (VOL_ENCRYPTABLE | VOL_NONREMOVABLE)) == - (VOL_ENCRYPTABLE | VOL_NONREMOVABLE); -} - -int cryptfs_enable(char *howarg, char *passwd) +int cryptfs_crypto_complete(void) { - // Code removed because it needs other parts of vold that aren't needed for decryption - return -1; + return -1; } -int cryptfs_changepw(char *newpw) +int cryptfs_check_passwd(const char *passwd) { - struct crypt_mnt_ftr crypt_ftr; - unsigned char encrypted_master_key[KEY_LEN_BYTES], decrypted_master_key[KEY_LEN_BYTES]; - unsigned char salt[SALT_LEN]; - char real_blkdev[MAXPATHLEN]; + char pwbuf[256]; + char crypto_blkdev_data[MAXPATHLEN]; + int rc = -1; - /* This is only allowed after we've successfully decrypted the master key */ - if (! master_key_saved) { - SLOGE("Key not saved, aborting"); - return -1; - } + strcpy(pwbuf, passwd); + rc = test_mount_encrypted_fs(pwbuf, DATA_MNT_POINT, "userdata", crypto_blkdev_data); - property_get("ro.crypto.fs_real_blkdev", real_blkdev, ""); - if (strlen(real_blkdev) == 0) { - SLOGE("Can't find real blkdev"); - return -1; - } +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG + if(using_samsung_encryption) { - /* get key */ - if (get_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt)) { - SLOGE("Error getting crypt footer and key"); - return -1; + int rc2 = 1; +#ifndef RECOVERY_SDCARD_ON_DATA + // internal storage for non data/media devices + if(!rc) { + strcpy(pwbuf, passwd); + rc2 = test_mount_encrypted_fs_sd( + pwbuf, EXPAND(TW_INTERNAL_STORAGE_PATH), + EXPAND(TW_INTERNAL_STORAGE_MOUNT_POINT)); + } +#endif +#ifdef TW_EXTERNAL_STORAGE_PATH + printf("Temp mounting /data\n"); + // mount data so mount_ecryptfs_drive can access edk in /data/system/ + rc2 = mount(crypto_blkdev_data, DATA_MNT_POINT, CRYPTO_FS_TYPE, MS_RDONLY, ""); + // external sd + char decrypt_external[256], external_blkdev[256]; + property_get("ro.crypto.external_encrypted", decrypt_external, "0"); + // First we have to mount the external storage + if (!rc2 && strcmp(decrypt_external, "1") == 0) { + printf("Mounting external...\n"); + property_get("ro.crypto.external_blkdev", external_blkdev, ""); + rc2 = mount( + external_blkdev, EXPAND(TW_EXTERNAL_STORAGE_PATH), + "vfat", MS_RDONLY, ""); + } + // Mount the external storage as ecryptfs so that ecryptfs can act as a pass-through + if (!rc2) { + printf("Mounting external with ecryptfs...\n"); + strcpy(pwbuf, passwd); + rc2 = mount_ecryptfs_drive( + pwbuf, EXPAND(TW_EXTERNAL_STORAGE_PATH), + EXPAND(TW_EXTERNAL_STORAGE_PATH), 0); + } else { + printf("Unable to mount external storage with ecryptfs.\n"); + umount(EXPAND(TW_EXTERNAL_STORAGE_PATH)); + } + umount(DATA_MNT_POINT); } - - encrypt_master_key(newpw, salt, saved_master_key, encrypted_master_key); - - /* save the key */ - put_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt); - - return 0; +#endif // #ifdef TW_EXTERNAL_STORAGE_PATH +#endif // #ifdef TW_INCLUDE_CRYPTO_SAMSUNG + return rc; } diff --git a/crypto/ics/cryptfs.h b/crypto/ics/cryptfs.h index 1c1bc1aea..e2fb7a7f3 100644 --- a/crypto/ics/cryptfs.h +++ b/crypto/ics/cryptfs.h @@ -25,6 +25,13 @@ * of the partition. */ +#ifndef __CRYPTFS_H__ +#define __CRYPTFS_H__ + +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG +#include "../libcrypt_samsung/include/libcrypt_samsung.h" +#endif + #define CRYPT_FOOTER_OFFSET 0x4000 #define MAX_CRYPTO_TYPE_NAME_LEN 64 @@ -37,11 +44,16 @@ #define CRYPT_ENCRYPTION_IN_PROGRESS 0x2 /* Set when starting encryption, * clear when done before rebooting */ +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG +#define CRYPT_MNT_MAGIC_SAMSUNG 0xD0B5B1C5 +#endif #define CRYPT_MNT_MAGIC 0xD0B5B1C4 #define __le32 unsigned int #define __le16 unsigned short int +#pragma pack(1) + struct crypt_mnt_ftr { __le32 magic; /* See above */ __le16 major_version; @@ -53,37 +65,25 @@ struct crypt_mnt_ftr { __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 + char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption needed to decrypt this partition, null terminated */ +#ifdef TW_INCLUDE_CRYPTO_SAMSUNG + edk_payload_t edk_payload; + __le32 unknown_end; +#endif }; -struct volume_info { - unsigned int size; - unsigned int flags; - struct crypt_mnt_ftr crypt_ftr; - char mnt_point[256]; - char blk_dev[256]; - char crypto_blkdev[256]; - char label[256]; -}; -#define VOL_NONREMOVABLE 0x1 -#define VOL_ENCRYPTABLE 0x2 +#pragma pack() + #ifdef __cplusplus extern "C" { #endif - int cryptfs_crypto_complete(void); - int cryptfs_check_passwd(char *pw); - int cryptfs_verify_passwd(char *newpw); - int cryptfs_restart(void); - int cryptfs_enable(char *flag, char *passwd); - int cryptfs_changepw(char *newpw); - int cryptfs_setup_volume(const char *label, int major, int minor, - char *crypto_dev_path, unsigned int max_pathlen, - int *new_major, int *new_minor); - int cryptfs_revert_volume(const char *label); + int cryptfs_check_passwd(const char *pw); #ifdef __cplusplus } #endif +#endif // __CRYPTFS_H__ + diff --git a/crypto/libcrypt_samsung/Android.mk b/crypto/libcrypt_samsung/Android.mk new file mode 100644 index 000000000..6e0e86903 --- /dev/null +++ b/crypto/libcrypt_samsung/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH := $(call my-dir) + +ifneq ($(TARGET_SIMULATOR),true) + +include $(CLEAR_VARS) +LOCAL_MODULE := libcrypt_samsung +LOCAL_SRC_FILES := $(LOCAL_MODULE).c +LOCAL_MODULE_TAGS := eng +include $(BUILD_STATIC_LIBRARY) + +endif diff --git a/crypto/libcrypt_samsung/include/libcrypt_samsung.h b/crypto/libcrypt_samsung/include/libcrypt_samsung.h new file mode 100644 index 000000000..48c7b3e6d --- /dev/null +++ b/crypto/libcrypt_samsung/include/libcrypt_samsung.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013 a3955269 all rights reversed, no rights reserved. + */ + +#ifndef __LIBCRYPT_SAMSUNG_H__ +#define __LIBCRYPT_SAMSUNG_H__ + +////////////////////////////////////////////////////////////////////////////// +// Name Address Ordinal +// ---- ------- ------- +// SECKM_AES_set_encrypt_key 000010D8 +// SECKM_AES_set_decrypt_key 00001464 +// SECKM_AES_encrypt 00001600 +// SECKM_AES_decrypt 00001A10 +// SECKM_aes_selftest 00001D94 +// verify_EDK 00001F7C +// encrypt_dek 00001FC8 +// decrypt_EDK 000020D4 +// change_EDK 0000218C +// generate_dek_salt 000022A4 +// create_EDK 000023A0 +// free_DEK 000024DC +// alloc_DEK 000024F4 +// SECKM_HMAC_SHA256 00002500 +// SECKM_HMAC_SHA256_selftest 00002690 +// pbkdf 000026FC +// pbkdf_selftest 00002898 +// _SECKM_PRNG_get16 00002958 +// SECKM_PRNG_get16 00002C48 +// _SECKM_PRNG_init 00002C54 +// SECKM_PRNG_selftest 00002F38 +// SECKM_PRNG_set_seed 00002FF0 +// SECKM_PRNG_init 00002FF8 +// SECKM_SHA256_Transform 00003004 +// SECKM_SHA256_Final 000031D8 +// SECKM_SHA256_Update 00003330 +// SECKM_SHA256_Init 000033FC +// SECKM_SHA2_selftest 00003430 +// integrity_check 00003488 +// update_system_property 00003580 +// setsec_km_fips_status 00003630 +// _all_checks 00003684 +// get_fips_status 000036D4 + + +// EDK Payload is defined as: +// Encrypted DEK – EDK itself +// HMAC of EDK (32 bytes ???) +// Salt 16 bytes + +#define EDK_MAGIC 0x1001e4b1 + +#pragma pack(1) + +typedef struct { + unsigned int magic; // EDK_MAGIC + unsigned int flags; // 2 + unsigned int zeros[6]; +} dek_t; + +typedef struct { + unsigned char data[32]; +} edk_t; + + +// size 0x70 -> 112 +typedef struct { + dek_t dek; + edk_t edk; + unsigned char hmac[32]; + unsigned char salt[16]; +} edk_payload_t; + +#pragma pack() + +////////////////////////////////////////////////////////////////////////////// + +int decrypt_EDK( + dek_t *dek, const edk_payload_t *edk, /*const*/ char *passwd); + +typedef int (*decrypt_EDK_t)( + dek_t *dek, const edk_payload_t *edk, /*const*/ char *passwd); + + +int verify_EDK(const edk_payload_t *edk, const char *passwd); +//change_EDK() +//create_EDK() + +// internally just mallocs 32 bytes +dek_t *alloc_DEK(); +void free_DEK(dek_t *dek); +//encrypt_dek() +//generate_dek_salt() + +//pbkdf(_buf_, "passwordPASSWORDpassword", 0x18, "saltSALTsaltSALTsaltSALTsaltSALTsalt", 0x24, 0x1000, 0x140); +int pbkdf( + void *buf, void *pw, int pwlen, void *salt, int saltlen, int hashcnt, + int keylen); + +// getprop("rw.km_fips_status") +// "ready, undefined, error_selftest, error_integrity" +int get_fips_status(); + +////////////////////////////////////////////////////////////////////////////// +// +// libsec_ecryptfs.so (internally uses libkeyutils.so) +// +// Name Address Ordinal +// ---- ------- ------- +// unmount_ecryptfs_drive 00000A78 +// mount_ecryptfs_drive 00000B48 +// fips_read_edk 00000E44 +// fips_save_edk 00000EA4 +// fips_create_edk 00000F20 +// fips_change_password 00001018 +// fips_delete_edk 00001124 +// + +// might depend on /data beeing mounted for reading /data/system/edk_p_sd +// +// filter +// 0: building options without file encryption filtering. +// 1: building options with media files filtering. +// 2: building options with all new files filtering. + +int mount_ecryptfs_drive( + const char *passwd, const char *source, const char *target, int filter); + +typedef int (*mount_ecryptfs_drive_t)( + const char *passwd, const char *source, const char *target, int filter); + +// calls 2 times umount2(source, MNT_EXPIRE) +int unmount_ecryptfs_drive( + const char *source); + +////////////////////////////////////////////////////////////////////////////// + +#endif // #ifndef __LIBCRYPT_SAMSUNG_H__ + +////////////////////////////////////////////////////////////////////////////// + diff --git a/crypto/libcrypt_samsung/libcrypt_samsung.c b/crypto/libcrypt_samsung/libcrypt_samsung.c new file mode 100644 index 000000000..4b9b9c5d5 --- /dev/null +++ b/crypto/libcrypt_samsung/libcrypt_samsung.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 a3955269 all rights reversed, no rights reserved. + */ + +////////////////////////////////////////////////////////////////////////////// + +#include <string.h> +#include <stdio.h> +#include <dlfcn.h> + +#include "include/libcrypt_samsung.h" + +////////////////////////////////////////////////////////////////////////////// +void xconvert_key_to_hex_ascii(unsigned char *master_key, unsigned int keysize, + char *master_key_ascii) +{ + unsigned int i, a; + unsigned char nibble; + + for (i=0, a=0; i<keysize; i++, a+=2) { + /* For each byte, write out two ascii hex digits */ + nibble = (master_key[i] >> 4) & 0xf; + master_key_ascii[a] = nibble + (nibble > 9 ? 0x37 : 0x30); + + nibble = master_key[i] & 0xf; + master_key_ascii[a+1] = nibble + (nibble > 9 ? 0x37 : 0x30); + } + + /* Add the null termination */ + master_key_ascii[a] = '\0'; + +} + +int decrypt_EDK( + dek_t *dek, const edk_payload_t *edk, /*const*/ char *passwd) +{ + void *lib = dlopen("libsec_km.so", RTLD_LAZY); + + if(!lib) + return -100; + + int r = -101; + decrypt_EDK_t sym = (decrypt_EDK_t)dlsym(lib, "decrypt_EDK"); + if(sym) + r = sym(dek, edk, passwd); + + dlclose(lib); + + return r; +} + +int mount_ecryptfs_drive( + const char *passwd, const char *source, const char *target, int filter) +{ + void *lib = dlopen("libsec_ecryptfs.so", RTLD_LAZY); + if(!lib) + return -100; + + int r = -101; + mount_ecryptfs_drive_t sym = (mount_ecryptfs_drive_t)dlsym(lib, "mount_ecryptfs_drive"); + if(sym) + r = sym(passwd, source, target, filter); + + dlclose(lib); + + return r; +} + diff --git a/partitionmanager.cpp b/partitionmanager.cpp index 95f010093..26143831f 100644 --- a/partitionmanager.cpp +++ b/partitionmanager.cpp @@ -1567,12 +1567,44 @@ int TWPartitionManager::Decrypt_Device(string Password) { property_set("ro.crypto.fs_options", CRYPTO_FS_OPTIONS); property_set("ro.crypto.fs_flags", CRYPTO_FS_FLAGS); property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC); + +#ifdef CRYPTO_SD_FS_TYPE + property_set("ro.crypto.sd_fs_type", CRYPTO_SD_FS_TYPE); + property_set("ro.crypto.sd_fs_real_blkdev", CRYPTO_SD_REAL_BLKDEV); + property_set("ro.crypto.sd_fs_mnt_point", EXPAND(TW_INTERNAL_STORAGE_PATH)); +#endif + + property_set("rw.km_fips_status", "ready"); + +#endif + + // some samsung devices store "footer" on efs partition + TWPartition *efs = Find_Partition_By_Path("/efs"); + if(efs && !efs->Is_Mounted()) + efs->Mount(false); + else + efs = 0; +#ifdef TW_EXTERNAL_STORAGE_PATH + TWPartition* sdcard = Find_Partition_By_Path(EXPAND(TW_EXTERNAL_STORAGE_PATH)); + if (sdcard) { + property_set("ro.crypto.external_encrypted", "1"); + property_set("ro.crypto.external_blkdev", sdcard->Actual_Block_Device.c_str()); + } else { + property_set("ro.crypto.external_encrypted", "0"); + } #endif + strcpy(cPassword, Password.c_str()); - if (cryptfs_check_passwd(cPassword) != 0) { + int pwret = cryptfs_check_passwd(cPassword); + + if (pwret != 0) { LOGE("Failed to decrypt data.\n"); return -1; } + + if(efs) + efs->UnMount(false); + property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error"); if (strcmp(crypto_blkdev, "error") == 0) { LOGE("Error retrieving decrypted data block device.\n"); @@ -1585,6 +1617,25 @@ int TWPartitionManager::Decrypt_Device(string Password) { dat->Decrypted_Block_Device = crypto_blkdev; dat->Setup_File_System(false); ui_print("Data successfully decrypted, new block device: '%s'\n", crypto_blkdev); + +#ifdef CRYPTO_SD_FS_TYPE + char crypto_blkdev_sd[255]; + property_get("ro.crypto.sd_fs_crypto_blkdev", crypto_blkdev_sd, "error"); + if (strcmp(crypto_blkdev_sd, "error") == 0) { + LOGE("Error retrieving decrypted data block device.\n"); + } else if(TWPartition* emmc = Find_Partition_By_Path(TW_INTERNAL_STORAGE_PATH)){ + emmc->Is_Decrypted = true; + emmc->Decrypted_Block_Device = crypto_blkdev_sd; + emmc->Setup_File_System(false); + ui_print("Internal SD successfully decrypted, new block device: '%s'\n", crypto_blkdev_sd); + } + +#ifdef TW_EXTERNAL_STORAGE_PATH + sdcard->Is_Decrypted = true; + sdcard->Setup_File_System(false); +#endif //ifdef TW_EXTERNAL_STORAGE_PATH +#endif //ifdef CRYPTO_SD_FS_TYPE + // Sleep for a bit so that the device will be ready sleep(1); #ifdef RECOVERY_SDCARD_ON_DATA diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk index 048077a22..e260598d3 100644 --- a/prebuilt/Android.mk +++ b/prebuilt/Android.mk @@ -55,6 +55,11 @@ endif ifeq ($(TW_INCLUDE_JB_CRYPTO), true) RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcrypto.so endif +ifeq ($(TW_INCLUDE_CRYPTO_SAMSUNG), true) + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libsec_km.so + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libsec_ecryptfs.so + RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeyutils.so +endif ifeq ($(TARGET_USERIMAGES_USE_EXT4), true) RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/make_ext4fs endif |