From 6ff55cefd060b4c8f6c0fa97d5521516f9ee43f1 Mon Sep 17 00:00:00 2001 From: a3955269 Date: Tue, 8 Jan 2013 16:14:56 +0000 Subject: Add Samsung TouchWiz decryption Change-Id: I418680e59372160dabfe3e2d5f0208229aa151ae --- crypto/ics/cryptfs.c | 809 +++++++++++---------------------------------------- crypto/ics/cryptfs.h | 44 +-- 2 files changed, 195 insertions(+), 658 deletions(-) (limited to 'crypto/ics') 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; ifs_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 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; iflags & (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__ + -- cgit v1.2.3