diff options
author | Ethan Yonker <dees_troy@teamw.in> | 2014-11-25 22:00:52 +0100 |
---|---|---|
committer | Dees Troy <dees_troy@teamw.in> | 2014-12-04 17:30:16 +0100 |
commit | 253368a0726120efa57664cdd1d088af099a3d81 (patch) | |
tree | 56cf3b08cdf70d016a2411fba977f7cd143bc265 /crypto | |
parent | bootable recovery: we upgraded to 5.0.1 (diff) | |
download | android_bootable_recovery-253368a0726120efa57664cdd1d088af099a3d81.tar android_bootable_recovery-253368a0726120efa57664cdd1d088af099a3d81.tar.gz android_bootable_recovery-253368a0726120efa57664cdd1d088af099a3d81.tar.bz2 android_bootable_recovery-253368a0726120efa57664cdd1d088af099a3d81.tar.lz android_bootable_recovery-253368a0726120efa57664cdd1d088af099a3d81.tar.xz android_bootable_recovery-253368a0726120efa57664cdd1d088af099a3d81.tar.zst android_bootable_recovery-253368a0726120efa57664cdd1d088af099a3d81.zip |
Diffstat (limited to '')
34 files changed, 53 insertions, 8281 deletions
diff --git a/crypto/cryptfs/Android.mk b/crypto/cryptfs/Android.mk deleted file mode 100644 index f0388c228..000000000 --- a/crypto/cryptfs/Android.mk +++ /dev/null @@ -1,54 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) -ifeq ($(TW_INCLUDE_CRYPTO), true) -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 += libminzip libunz -LOCAL_STATIC_LIBRARIES += libpixelflinger_static libpng libmincrypttwrp -LOCAL_SHARED_LIBRARIES += libz libc libstlport libcutils libstdc++ 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) -endif diff --git a/crypto/cryptfs/cryptfs.c b/crypto/cryptfs/cryptfs.c deleted file mode 100644 index 59e7added..000000000 --- a/crypto/cryptfs/cryptfs.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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/cryptsettings/Android.mk b/crypto/cryptsettings/Android.mk deleted file mode 100644 index 3a5704891..000000000 --- a/crypto/cryptsettings/Android.mk +++ /dev/null @@ -1,17 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) -ifeq ($(TW_INCLUDE_CRYPTO), true) -LOCAL_SRC_FILES:= \ - cryptsettings.c -LOCAL_CFLAGS:= -g -c -W -LOCAL_MODULE:=cryptsettings -LOCAL_MODULE_TAGS:= eng -LOCAL_SHARED_LIBRARIES += libc libcutils -ifeq ($(TW_INCLUDE_JB_CRYPTO), true) -LOCAL_CFLAGS += -DTW_INCLUDE_JB_CRYPTO -LOCAL_STATIC_LIBRARIES += libfs_mgrtwrp -endif -LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES -LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities -include $(BUILD_EXECUTABLE) -endif diff --git a/crypto/cryptsettings/cryptsettings.c b/crypto/cryptsettings/cryptsettings.c deleted file mode 100644 index 4fa2b9354..000000000 --- a/crypto/cryptsettings/cryptsettings.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <sys/types.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <fcntl.h> -#ifdef TW_INCLUDE_JB_CRYPTO -#include "../crypto/fs_mgr/include/fs_mgr.h" -#endif - -#include "cutils/properties.h" - -#ifndef PROPERTY_VALUE_MAX -#define PROPERTY_VALUE_MAX 255 -#endif -#ifndef FSTAB_PREFIX -#define FSTAB_PREFIX "/fstab." -#endif - -int main(void) -{ - char prop[PROPERTY_VALUE_MAX]; - char key_loc[PROPERTY_VALUE_MAX]; - char blk_dev[PROPERTY_VALUE_MAX]; - char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; - - printf("This tool will gather the build flags needed for decryption support for TWRP.\n"); - printf("This tool comes with no warranties whatsoever.\n"); - printf("http://teamw.in\n\n"); - property_get("ro.crypto.state", prop, "encrypted"); - if (strcmp(prop, "encrypted") != 0) - printf("Your device is not encrypted, continuing anyway.\n\nTW_INCLUDE_CRYPTO := true\n"); - property_get("ro.crypto.fs_type", prop, "ERROR"); - printf("TW_CRYPTO_FS_TYPE := \"%s\"\n", prop); - property_get("ro.crypto.fs_real_blkdev", prop, "ERROR"); - printf("TW_CRYPTO_REAL_BLKDEV := \"%s\"\n", prop); - property_get("ro.crypto.fs_mnt_point", prop, "ERROR"); - printf("TW_CRYPTO_MNT_POINT := \"%s\"\n", prop); - property_get("ro.crypto.fs_options", prop, "ERROR"); - printf("TW_CRYPTO_FS_OPTIONS := \"%s\"\n", prop); - property_get("ro.crypto.fs_flags", prop, "ERROR"); - printf("TW_CRYPTO_FS_FLAGS := \"%s\"\n", prop); - property_get("ro.crypto.keyfile.userdata", prop, "footer"); - printf("TW_CRYPTO_KEY_LOC := \"%s\"\n", prop); -#ifdef TW_INCLUDE_JB_CRYPTO - printf("\n*** NEW FOR JELLY BEAN:\n"); - strcpy(fstab_filename, FSTAB_PREFIX); - property_get("ro.hardware", fstab_filename + sizeof(FSTAB_PREFIX) - 1, ""); - fs_mgr_get_crypt_info(fstab_filename, key_loc, blk_dev, sizeof(key_loc)); - printf("fstab file location: '%s'\n\nTW_INCLUDE_JB_CRYPTO := true\n", fstab_filename); -#endif - - return 0; -} diff --git a/crypto/crypttools/Android.mk b/crypto/crypttools/Android.mk deleted file mode 100644 index fc62583c4..000000000 --- a/crypto/crypttools/Android.mk +++ /dev/null @@ -1,15 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) -ifeq ($(TW_INCLUDE_JB_CRYPTO), true) -LOCAL_SRC_FILES:= \ - getfooter.c -LOCAL_CFLAGS:= -g -c -W -LOCAL_MODULE:=getfooter -LOCAL_MODULE_TAGS:= eng -LOCAL_STATIC_LIBRARIES += libfs_mgrtwrp libc libcutils -LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES -LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities -LOCAL_FORCE_STATIC_EXECUTABLE := true -LOCAL_C_INCLUDES := $(commands_recovery_local_path)/crypto/jb/ -include $(BUILD_EXECUTABLE) -endif
\ No newline at end of file diff --git a/crypto/crypttools/getfooter.c b/crypto/crypttools/getfooter.c deleted file mode 100644 index aa7f88e84..000000000 --- a/crypto/crypttools/getfooter.c +++ /dev/null @@ -1,219 +0,0 @@ -#include <sys/types.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <linux/dm-ioctl.h> -#include <sys/mount.h> -#include "../fs_mgr/include/fs_mgr.h" -#include "cryptfs.h" - -#include "cutils/properties.h" - -#ifndef PROPERTY_VALUE_MAX -#define PROPERTY_VALUE_MAX 255 -#endif -#ifndef FSTAB_PREFIX -#define FSTAB_PREFIX "/fstab." -#endif -#ifndef KEY_IN_FOOTER -#define KEY_IN_FOOTER "footer" -#endif - -struct fstab *fstab; - -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; -} - -int get_crypt_ftr_info(char **metadata_fname, off64_t *off) -{ - static int cached_data = 0; - static off64_t cached_off = 0; - static char cached_metadata_fname[PROPERTY_VALUE_MAX] = ""; - int fd; - char key_loc[PROPERTY_VALUE_MAX]; - char real_blkdev[PROPERTY_VALUE_MAX]; - unsigned int nr_sec; - int rc = -1; - - fs_mgr_get_crypt_info(fstab, key_loc, real_blkdev, sizeof(key_loc)); - - if (!strcmp(key_loc, KEY_IN_FOOTER)) { - if ( (fd = open(real_blkdev, O_RDWR)) < 0) { - printf("Cannot open real block device %s\n", real_blkdev); - return -1; - } - - if ((nr_sec = get_blkdev_size(fd))) { - /* 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. - */ - strlcpy(cached_metadata_fname, real_blkdev, sizeof(cached_metadata_fname)); - cached_off = ((off64_t)nr_sec * 512) - CRYPT_FOOTER_OFFSET; - cached_data = 1; - } else { - printf("Cannot get size of block device %s\n", real_blkdev); - } - close(fd); - } else { - strlcpy(cached_metadata_fname, key_loc, sizeof(cached_metadata_fname)); - cached_off = 0; - cached_data = 1; - } - - if (cached_data) { - if (metadata_fname) { - *metadata_fname = cached_metadata_fname; - } - if (off) { - *off = cached_off; - } - rc = 0; - } - - return rc; -} - -int get_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr) -{ - int fd; - unsigned int nr_sec, cnt; - off64_t starting_off; - int rc = -1; - char *fname = NULL; - struct stat statbuf; - - if (get_crypt_ftr_info(&fname, &starting_off)) { - printf("Unable to get crypt_ftr_info\n"); - return -1; - } - if (fname[0] != '/') { - printf("Unexpected value for crypto key location '%s'\n", fname); - //return -1; - } - if ( (fd = open(fname, O_RDWR)) < 0) { - printf("Cannot open footer file %s for get\n", fname); - return -1; - } - - /* Make sure it's 16 Kbytes in length */ - fstat(fd, &statbuf); - if (S_ISREG(statbuf.st_mode) && (statbuf.st_size != 0x4000)) { - printf("footer file %s is not the expected size!\n", fname); - close(fd); - return -1; - } - - /* Seek to the start of the crypt footer */ - if (lseek64(fd, starting_off, SEEK_SET) == -1) { - printf("Cannot seek to real block device footer\n"); - close(fd); - return -1; - } - - if ( (cnt = read(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr))) != sizeof(struct crypt_mnt_ftr)) { - printf("Cannot read real block device footer\n"); - close(fd); - return -1; - } - close(fd); - return 0; -} - -int main(void) -{ - char key_loc[PROPERTY_VALUE_MAX]; - char blk_dev[PROPERTY_VALUE_MAX]; - char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; - struct stat st; - struct crypt_mnt_ftr crypt_ftr; - int fdout; - - printf("This tool comes with no warranties whatsoever.\n"); - printf("http://teamw.in\n\n"); - strcpy(fstab_filename, FSTAB_PREFIX); - property_get("ro.hardware", fstab_filename + sizeof(FSTAB_PREFIX) - 1, ""); - - if (stat(fstab_filename, &st) != 0) { - printf("Cannot locate fstab file '%s'\n", fstab_filename); - return -1; - } - - fstab = fs_mgr_read_fstab(fstab_filename); - if (!fstab) { - printf("failed to open %s\n", fstab_filename); - return -1; - } - - fs_mgr_get_crypt_info(fstab, key_loc, blk_dev, sizeof(blk_dev)); - - if (get_crypt_ftr_and_key(&crypt_ftr)) { - printf("Error getting crypt footer and key\n"); - return -1; - } - - if ( (fdout = open("/footerfile", O_WRONLY | O_CREAT, 0644)) < 0) { - printf("Cannot open output file /footerfile\n"); - return -1; - } - if (write(fdout, (void*) &crypt_ftr, sizeof(struct crypt_mnt_ftr)) != sizeof(struct crypt_mnt_ftr)) { - printf("Failed to write footer.\n"); - } - close(fdout); - - if (!strcmp(key_loc, KEY_IN_FOOTER)) { - unsigned int nr_sec, cnt; - off64_t off = 0; - char buffer[CRYPT_FOOTER_OFFSET]; - int fd; - - printf("\n\nDumping footer from '%s'...\n", blk_dev); - if ( (fd = open(blk_dev, O_RDONLY)) < 0) { - printf("Cannot open real block device %s\n", blk_dev); - return -1; - } - - if ((nr_sec = get_blkdev_size(fd))) { - off = ((off64_t)nr_sec * 512) - CRYPT_FOOTER_OFFSET; - } else { - printf("Cannot get size of block device %s\n", blk_dev); - close(fd); - return -1; - } - printf("Size is %llu, offset is %llu\n", ((off64_t)nr_sec * 512), off); - if (lseek64(fd, off, SEEK_SET) == -1) { - printf("Cannot seek to real block device footer\n"); - close(fd); - return -1; - } - - if ( (cnt = read(fd, buffer, sizeof(buffer))) != sizeof(buffer)) { - printf("Cannot read real block device footer\n"); - close(fd); - return -1; - } - close(fd); - if ( (fdout = open("/footerdump", O_WRONLY | O_CREAT, 0644)) < 0) { - printf("Cannot open output file /footerdump\n"); - return -1; - } - if (write(fdout, buffer, sizeof(buffer)) != sizeof(buffer)) { - printf("Failed to write footer.\n"); - } - close(fdout); - } - - return 0; -} diff --git a/crypto/fs_mgr/Android.mk b/crypto/fs_mgr/Android.mk deleted file mode 100644 index 8dd9d4ca2..000000000 --- a/crypto/fs_mgr/Android.mk +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2011 The Android Open Source Project -ifeq ($(TW_INCLUDE_JB_CRYPTO), true) -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c - -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include - -LOCAL_MODULE:= libfs_mgrtwrp -LOCAL_SHARED_LIBRARIES := libext4_utils -LOCAL_STATIC_LIBRARIES := liblogwraptwrp libmincrypttwrp -LOCAL_C_INCLUDES += \ - system/extras/ext4_utils \ - $(commands_recovery_local_path)/libmincrypt/includes -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include - -include $(BUILD_STATIC_LIBRARY) - - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= fs_mgr_main.c - -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include - -LOCAL_MODULE:= fs_mgrtwrp - -LOCAL_MODULE_TAGS := optional -LOCAL_FORCE_STATIC_EXECUTABLE := true -LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin -LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) - -LOCAL_STATIC_LIBRARIES := libfs_mgrtwrp liblogwraptwrp libcutils liblog libc libmincrypttwrp libext4_utils_static - -include $(BUILD_EXECUTABLE) - -endif diff --git a/crypto/fs_mgr/fs_mgr.c b/crypto/fs_mgr/fs_mgr.c deleted file mode 100644 index 3aa9e6039..000000000 --- a/crypto/fs_mgr/fs_mgr.c +++ /dev/null @@ -1,948 +0,0 @@ -/* - * Copyright (C) 2012 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <ctype.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <libgen.h> -#include <time.h> -//#include <sys/swap.h> -/* XXX These need to be obtained from kernel headers. See b/9336527 */ -#define SWAP_FLAG_PREFER 0x8000 -#define SWAP_FLAG_PRIO_MASK 0x7fff -#define SWAP_FLAG_PRIO_SHIFT 0 -#define SWAP_FLAG_DISCARD 0x10000 - -#include <linux/loop.h> -#include <private/android_filesystem_config.h> -#include <cutils/partition_utils.h> -#include <cutils/properties.h> -#include <logwrap/logwrap.h> - -#include "mincrypt/rsa.h" -#include "mincrypt/sha.h" -#include "mincrypt/sha256.h" - -#include "fs_mgr_priv.h" -#include "fs_mgr_priv_verity.h" - -#define KEY_LOC_PROP "ro.crypto.keyfile.userdata" -#define KEY_IN_FOOTER "footer" - -#define E2FSCK_BIN "/system/bin/e2fsck" -#define MKSWAP_BIN "/system/bin/mkswap" - -#define FSCK_LOG_FILE "/dev/fscklogs/log" - -#define ZRAM_CONF_DEV "/sys/block/zram0/disksize" - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) - -struct flag_list { - const char *name; - unsigned flag; -}; - -static struct flag_list mount_flags[] = { - { "noatime", MS_NOATIME }, - { "noexec", MS_NOEXEC }, - { "nosuid", MS_NOSUID }, - { "nodev", MS_NODEV }, - { "nodiratime", MS_NODIRATIME }, - { "ro", MS_RDONLY }, - { "rw", 0 }, - { "remount", MS_REMOUNT }, - { "bind", MS_BIND }, - { "rec", MS_REC }, - { "unbindable", MS_UNBINDABLE }, - { "private", MS_PRIVATE }, - { "slave", MS_SLAVE }, - { "shared", MS_SHARED }, - { "defaults", 0 }, - { 0, 0 }, -}; - -static struct flag_list fs_mgr_flags[] = { - { "wait", MF_WAIT }, - { "check", MF_CHECK }, - { "encryptable=",MF_CRYPT }, - { "nonremovable",MF_NONREMOVABLE }, - { "voldmanaged=",MF_VOLDMANAGED}, - { "length=", MF_LENGTH }, - { "recoveryonly",MF_RECOVERYONLY }, - { "swapprio=", MF_SWAPPRIO }, - { "zramsize=", MF_ZRAMSIZE }, - { "verify", MF_VERIFY }, - { "noemulatedsd", MF_NOEMULATEDSD }, - { "defaults", 0 }, - { 0, 0 }, -}; - -struct fs_mgr_flag_values { - char *key_loc; - long long part_length; - char *label; - int partnum; - int swap_prio; - unsigned int zram_size; -}; - -/* - * gettime() - returns the time in seconds of the system's monotonic clock or - * zero on error. - */ -static time_t gettime(void) -{ - struct timespec ts; - int ret; - - ret = clock_gettime(CLOCK_MONOTONIC, &ts); - if (ret < 0) { - ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); - return 0; - } - - return ts.tv_sec; -} - -static int wait_for_file(const char *filename, int timeout) -{ - struct stat info; - time_t timeout_time = gettime() + timeout; - int ret = -1; - - while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0)) - usleep(10000); - - return ret; -} - -static int parse_flags(char *flags, struct flag_list *fl, - struct fs_mgr_flag_values *flag_vals, - char *fs_options, int fs_options_len) -{ - int f = 0; - int i; - char *p; - char *savep; - - /* initialize flag values. If we find a relevant flag, we'll - * update the value */ - if (flag_vals) { - memset(flag_vals, 0, sizeof(*flag_vals)); - flag_vals->partnum = -1; - flag_vals->swap_prio = -1; /* negative means it wasn't specified. */ - } - - /* initialize fs_options to the null string */ - if (fs_options && (fs_options_len > 0)) { - fs_options[0] = '\0'; - } - - p = strtok_r(flags, ",", &savep); - while (p) { - /* Look for the flag "p" in the flag list "fl" - * If not found, the loop exits with fl[i].name being null. - */ - for (i = 0; fl[i].name; i++) { - if (!strncmp(p, fl[i].name, strlen(fl[i].name))) { - f |= fl[i].flag; - if ((fl[i].flag == MF_CRYPT) && flag_vals) { - /* The encryptable flag is followed by an = and the - * location of the keys. Get it and return it. - */ - flag_vals->key_loc = strdup(strchr(p, '=') + 1); - } else if ((fl[i].flag == MF_LENGTH) && flag_vals) { - /* The length flag is followed by an = and the - * size of the partition. Get it and return it. - */ - flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0); - } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) { - /* The voldmanaged flag is followed by an = and the - * label, a colon and the partition number or the - * word "auto", e.g. - * voldmanaged=sdcard:3 - * Get and return them. - */ - char *label_start; - char *label_end; - char *part_start; - - label_start = strchr(p, '=') + 1; - label_end = strchr(p, ':'); - if (label_end) { - flag_vals->label = strndup(label_start, - (int) (label_end - label_start)); - part_start = strchr(p, ':') + 1; - if (!strcmp(part_start, "auto")) { - flag_vals->partnum = -1; - } else { - flag_vals->partnum = strtol(part_start, NULL, 0); - } - } else { - ERROR("Warning: voldmanaged= flag malformed\n"); - } - } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) { - flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0); - } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) { - flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0); - } - break; - } - } - - if (!fl[i].name) { - if (fs_options) { - /* It's not a known flag, so it must be a filesystem specific - * option. Add it to fs_options if it was passed in. - */ - strlcat(fs_options, p, fs_options_len); - strlcat(fs_options, ",", fs_options_len); - } else { - /* fs_options was not passed in, so if the flag is unknown - * it's an error. - */ - ERROR("Warning: unknown flag %s\n", p); - } - } - p = strtok_r(NULL, ",", &savep); - } - -out: - if (fs_options && fs_options[0]) { - /* remove the last trailing comma from the list of options */ - fs_options[strlen(fs_options) - 1] = '\0'; - } - - return f; -} - -/* Read a line of text till the next newline character. - * If no newline is found before the buffer is full, continue reading till a new line is seen, - * then return an empty buffer. This effectively ignores lines that are too long. - * On EOF, return null. - */ -static char *fs_getline(char *buf, int size, FILE *file) -{ - int cnt = 0; - int eof = 0; - int eol = 0; - int c; - - if (size < 1) { - return NULL; - } - - while (cnt < (size - 1)) { - c = getc(file); - if (c == EOF) { - eof = 1; - break; - } - - *(buf + cnt) = c; - cnt++; - - if (c == '\n') { - eol = 1; - break; - } - } - - /* Null terminate what we've read */ - *(buf + cnt) = '\0'; - - if (eof) { - if (cnt) { - return buf; - } else { - return NULL; - } - } else if (eol) { - return buf; - } else { - /* The line is too long. Read till a newline or EOF. - * If EOF, return null, if newline, return an empty buffer. - */ - while(1) { - c = getc(file); - if (c == EOF) { - return NULL; - } else if (c == '\n') { - *buf = '\0'; - return buf; - } - } - } -} - -struct fstab *fs_mgr_read_fstab(const char *fstab_path) -{ - FILE *fstab_file; - int cnt, entries; - int len; - char line[256]; - const char *delim = " \t"; - char *save_ptr, *p; - struct fstab *fstab; - struct fstab_rec *recs; - struct fs_mgr_flag_values flag_vals; -#define FS_OPTIONS_LEN 1024 - char tmp_fs_options[FS_OPTIONS_LEN]; - - fstab_file = fopen(fstab_path, "r"); - if (!fstab_file) { - ERROR("Cannot open file %s\n", fstab_path); - return 0; - } - - entries = 0; - while (fs_getline(line, sizeof(line), fstab_file)) { - /* if the last character is a newline, shorten the string by 1 byte */ - len = strlen(line); - if (line[len - 1] == '\n') { - line[len - 1] = '\0'; - } - /* Skip any leading whitespace */ - p = line; - while (isspace(*p)) { - p++; - } - /* ignore comments or empty lines */ - if (*p == '#' || *p == '\0') - continue; - entries++; - } - - if (!entries) { - ERROR("No entries found in fstab\n"); - return 0; - } - - /* Allocate and init the fstab structure */ - fstab = calloc(1, sizeof(struct fstab)); - fstab->num_entries = entries; - fstab->fstab_filename = strdup(fstab_path); - fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec)); - - fseek(fstab_file, 0, SEEK_SET); - - cnt = 0; - while (fs_getline(line, sizeof(line), fstab_file)) { - /* if the last character is a newline, shorten the string by 1 byte */ - len = strlen(line); - if (line[len - 1] == '\n') { - line[len - 1] = '\0'; - } - - /* Skip any leading whitespace */ - p = line; - while (isspace(*p)) { - p++; - } - /* ignore comments or empty lines */ - if (*p == '#' || *p == '\0') - continue; - - /* If a non-comment entry is greater than the size we allocated, give an - * error and quit. This can happen in the unlikely case the file changes - * between the two reads. - */ - if (cnt >= entries) { - ERROR("Tried to process more entries than counted\n"); - break; - } - - if (!(p = strtok_r(line, delim, &save_ptr))) { - ERROR("Error parsing mount source\n"); - return 0; - } - fstab->recs[cnt].blk_device = strdup(p); - - if (!(p = strtok_r(NULL, delim, &save_ptr))) { - ERROR("Error parsing mount_point\n"); - return 0; - } - fstab->recs[cnt].mount_point = strdup(p); - - if (!(p = strtok_r(NULL, delim, &save_ptr))) { - ERROR("Error parsing fs_type\n"); - return 0; - } - fstab->recs[cnt].fs_type = strdup(p); - - if (!(p = strtok_r(NULL, delim, &save_ptr))) { - ERROR("Error parsing mount_flags\n"); - return 0; - } - tmp_fs_options[0] = '\0'; - fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL, - tmp_fs_options, FS_OPTIONS_LEN); - - /* fs_options are optional */ - if (tmp_fs_options[0]) { - fstab->recs[cnt].fs_options = strdup(tmp_fs_options); - } else { - fstab->recs[cnt].fs_options = NULL; - } - - if (!(p = strtok_r(NULL, delim, &save_ptr))) { - ERROR("Error parsing fs_mgr_options\n"); - return 0; - } - fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, - &flag_vals, NULL, 0); - fstab->recs[cnt].key_loc = flag_vals.key_loc; - fstab->recs[cnt].length = flag_vals.part_length; - fstab->recs[cnt].label = flag_vals.label; - fstab->recs[cnt].partnum = flag_vals.partnum; - fstab->recs[cnt].swap_prio = flag_vals.swap_prio; - fstab->recs[cnt].zram_size = flag_vals.zram_size; - cnt++; - } - fclose(fstab_file); - - return fstab; -} - -void fs_mgr_free_fstab(struct fstab *fstab) -{ - int i; - - if (!fstab) { - return; - } - - for (i = 0; i < fstab->num_entries; i++) { - /* Free the pointers return by strdup(3) */ - free(fstab->recs[i].blk_device); - free(fstab->recs[i].mount_point); - free(fstab->recs[i].fs_type); - free(fstab->recs[i].fs_options); - free(fstab->recs[i].key_loc); - free(fstab->recs[i].label); - i++; - } - - /* Free the fstab_recs array created by calloc(3) */ - free(fstab->recs); - - /* Free the fstab filename */ - free(fstab->fstab_filename); - - /* Free fstab */ - free(fstab); -} - -static void check_fs(char *blk_device, char *fs_type, char *target) -{ - int status; - int ret; - long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID; - char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro"; - char *e2fsck_argv[] = { - E2FSCK_BIN, - "-y", - blk_device - }; - - /* Check for the types of filesystems we know how to check */ - if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) { - /* - * First try to mount and unmount the filesystem. We do this because - * the kernel is more efficient than e2fsck in running the journal and - * processing orphaned inodes, and on at least one device with a - * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes - * to do what the kernel does in about a second. - * - * After mounting and unmounting the filesystem, run e2fsck, and if an - * error is recorded in the filesystem superblock, e2fsck will do a full - * check. Otherwise, it does nothing. If the kernel cannot mount the - * filesytsem due to an error, e2fsck is still run to do a full check - * fix the filesystem. - */ - ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); - if (!ret) { - umount(target); - } - - INFO("Running %s on %s\n", E2FSCK_BIN, blk_device); - - ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, - &status, true, LOG_KLOG | LOG_FILE, - true, FSCK_LOG_FILE); - - if (ret < 0) { - /* No need to check for error in fork, we can't really handle it now */ - ERROR("Failed trying to run %s\n", E2FSCK_BIN); - } - } - - return; -} - -static void remove_trailing_slashes(char *n) -{ - int len; - - len = strlen(n) - 1; - while ((*(n + len) == '/') && len) { - *(n + len) = '\0'; - len--; - } -} - -/* - * Mark the given block device as read-only, using the BLKROSET ioctl. - * Return 0 on success, and -1 on error. - */ -static void fs_set_blk_ro(const char *blockdev) -{ - int fd; - int ON = 1; - - fd = open(blockdev, O_RDONLY); - if (fd < 0) { - // should never happen - return; - } - - ioctl(fd, BLKROSET, &ON); - close(fd); -} - -/* - * __mount(): wrapper around the mount() system call which also - * sets the underlying block device to read-only if the mount is read-only. - * See "man 2 mount" for return values. - */ -static int __mount(const char *source, const char *target, - const char *filesystemtype, unsigned long mountflags, - const void *data) -{ - int ret = mount(source, target, filesystemtype, mountflags, data); - - if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { - fs_set_blk_ro(source); - } - - return ret; -} - -static int fs_match(char *in1, char *in2) -{ - char *n1; - char *n2; - int ret; - - n1 = strdup(in1); - n2 = strdup(in2); - - remove_trailing_slashes(n1); - remove_trailing_slashes(n2); - - ret = !strcmp(n1, n2); - - free(n1); - free(n2); - - return ret; -} - -int fs_mgr_mount_all(struct fstab *fstab) -{ - int i = 0; - int encrypted = 0; - int ret = -1; - int mret; - - if (!fstab) { - return ret; - } - - for (i = 0; i < fstab->num_entries; i++) { - /* Don't mount entries that are managed by vold */ - if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { - continue; - } - - /* Skip swap and raw partition entries such as boot, recovery, etc */ - if (!strcmp(fstab->recs[i].fs_type, "swap") || - !strcmp(fstab->recs[i].fs_type, "emmc") || - !strcmp(fstab->recs[i].fs_type, "mtd")) { - continue; - } - - if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { - wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); - } - - if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { - check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type, - fstab->recs[i].mount_point); - } - - if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) { - if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { - ERROR("Could not set up verified partition, skipping!"); - continue; - } - } - - mret = __mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, - fstab->recs[i].fs_type, fstab->recs[i].flags, - fstab->recs[i].fs_options); - - if (!mret) { - /* Success! Go get the next one */ - continue; - } - - /* mount(2) returned an error, check if it's encrypted and deal with it */ - if ((fstab->recs[i].fs_mgr_flags & MF_CRYPT) && - !partition_wiped(fstab->recs[i].blk_device)) { - /* Need to mount a tmpfs at this mountpoint for now, and set - * properties that vold will query later for decrypting - */ - if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs", - MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { - ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n", - fstab->recs[i].mount_point); - goto out; - } - encrypted = 1; - } else { - ERROR("Cannot mount filesystem on %s at %s\n", - fstab->recs[i].blk_device, fstab->recs[i].mount_point); - goto out; - } - } - - if (encrypted) { - ret = 1; - } else { - ret = 0; - } - -out: - return ret; -} - -/* If tmp_mount_point is non-null, mount the filesystem there. This is for the - * tmp mount we do to check the user password - */ -int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, - char *tmp_mount_point) -{ - int i = 0; - int ret = -1; - char *m; - - if (!fstab) { - return ret; - } - - for (i = 0; i < fstab->num_entries; i++) { - if (!fs_match(fstab->recs[i].mount_point, n_name)) { - continue; - } - - /* We found our match */ - /* If this swap or a raw partition, report an error */ - if (!strcmp(fstab->recs[i].fs_type, "swap") || - !strcmp(fstab->recs[i].fs_type, "emmc") || - !strcmp(fstab->recs[i].fs_type, "mtd")) { - ERROR("Cannot mount filesystem of type %s on %s\n", - fstab->recs[i].fs_type, n_blk_device); - goto out; - } - - /* First check the filesystem if requested */ - if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { - wait_for_file(n_blk_device, WAIT_TIMEOUT); - } - - if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { - check_fs(n_blk_device, fstab->recs[i].fs_type, - fstab->recs[i].mount_point); - } - - if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) { - if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { - ERROR("Could not set up verified partition, skipping!"); - continue; - } - } - - /* Now mount it where requested */ - if (tmp_mount_point) { - m = tmp_mount_point; - } else { - m = fstab->recs[i].mount_point; - } - if (__mount(n_blk_device, m, fstab->recs[i].fs_type, - fstab->recs[i].flags, fstab->recs[i].fs_options)) { - ERROR("Cannot mount filesystem on %s at %s\n", - n_blk_device, m); - goto out; - } else { - ret = 0; - goto out; - } - } - - /* We didn't find a match, say so and return an error */ - ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); - -out: - return ret; -} - -/* - * mount a tmpfs filesystem at the given point. - * return 0 on success, non-zero on failure. - */ -int fs_mgr_do_tmpfs_mount(char *n_name) -{ - int ret; - - ret = mount("tmpfs", n_name, "tmpfs", - MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS); - if (ret < 0) { - ERROR("Cannot mount tmpfs filesystem at %s\n", n_name); - return -1; - } - - /* Success */ - return 0; -} - -int fs_mgr_unmount_all(struct fstab *fstab) -{ - int i = 0; - int ret = 0; - - if (!fstab) { - return -1; - } - - while (fstab->recs[i].blk_device) { - if (umount(fstab->recs[i].mount_point)) { - ERROR("Cannot unmount filesystem at %s\n", fstab->recs[i].mount_point); - ret = -1; - } - i++; - } - - return ret; -} - -/* This must be called after mount_all, because the mkswap command needs to be - * available. - */ -int fs_mgr_swapon_all(struct fstab *fstab) -{ - int i = 0; - int flags = 0; - int err = 0; - int ret = 0; - int status; - char *mkswap_argv[2] = { - MKSWAP_BIN, - NULL - }; - - if (!fstab) { - return -1; - } - - for (i = 0; i < fstab->num_entries; i++) { - /* Skip non-swap entries */ - if (strcmp(fstab->recs[i].fs_type, "swap")) { - continue; - } - - if (fstab->recs[i].zram_size > 0) { - /* A zram_size was specified, so we need to configure the - * device. There is no point in having multiple zram devices - * on a system (all the memory comes from the same pool) so - * we can assume the device number is 0. - */ - FILE *zram_fp; - - zram_fp = fopen(ZRAM_CONF_DEV, "r+"); - if (zram_fp == NULL) { - ERROR("Unable to open zram conf device " ZRAM_CONF_DEV); - ret = -1; - continue; - } - fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size); - fclose(zram_fp); - } - - if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { - wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); - } - - /* Initialize the swap area */ - mkswap_argv[1] = fstab->recs[i].blk_device; - err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv, - &status, true, LOG_KLOG, false, NULL); - if (err) { - ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device); - ret = -1; - continue; - } - - /* If -1, then no priority was specified in fstab, so don't set - * SWAP_FLAG_PREFER or encode the priority */ - if (fstab->recs[i].swap_prio >= 0) { - flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) & - SWAP_FLAG_PRIO_MASK; - flags |= SWAP_FLAG_PREFER; - } else { - flags = 0; - } - // requires sys/swap.h which is not available in older trees - // this entire function does not appear to be used for decrypt - err = -1; //swapon(fstab->recs[i].blk_device, flags); - if (err) { - ERROR("swapon failed for %s\n", fstab->recs[i].blk_device); - ret = -1; - } - } - - return ret; -} - -/* - * key_loc must be at least PROPERTY_VALUE_MAX bytes long - * - * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long - */ -int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size) -{ - int i = 0; - - if (!fstab) { - return -1; - } - /* Initialize return values to null strings */ - if (key_loc) { - *key_loc = '\0'; - } - if (real_blk_device) { - *real_blk_device = '\0'; - } - - /* Look for the encryptable partition to find the data */ - for (i = 0; i < fstab->num_entries; i++) { - /* Don't deal with vold managed enryptable partitions here */ - if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) { - continue; - } - if (!(fstab->recs[i].fs_mgr_flags & MF_CRYPT)) { - continue; - } - - /* We found a match */ - if (key_loc) { - strlcpy(key_loc, fstab->recs[i].key_loc, size); - } - if (real_blk_device) { - strlcpy(real_blk_device, fstab->recs[i].blk_device, size); - } - break; - } - - return 0; -} - -/* Add an entry to the fstab, and return 0 on success or -1 on error */ -int fs_mgr_add_entry(struct fstab *fstab, - const char *mount_point, const char *fs_type, - const char *blk_device, long long length) -{ - struct fstab_rec *new_fstab_recs; - int n = fstab->num_entries; - - new_fstab_recs = (struct fstab_rec *) - realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1)); - - if (!new_fstab_recs) { - return -1; - } - - /* A new entry was added, so initialize it */ - memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec)); - new_fstab_recs[n].mount_point = strdup(mount_point); - new_fstab_recs[n].fs_type = strdup(fs_type); - new_fstab_recs[n].blk_device = strdup(blk_device); - new_fstab_recs[n].length = 0; - - /* Update the fstab struct */ - fstab->recs = new_fstab_recs; - fstab->num_entries++; - - return 0; -} - -struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path) -{ - int i; - - if (!fstab) { - return NULL; - } - - for (i = 0; i < fstab->num_entries; i++) { - int len = strlen(fstab->recs[i].mount_point); - if (strncmp(path, fstab->recs[i].mount_point, len) == 0 && - (path[len] == '\0' || path[len] == '/')) { - return &fstab->recs[i]; - } - } - - return NULL; -} - -int fs_mgr_is_voldmanaged(struct fstab_rec *fstab) -{ - return fstab->fs_mgr_flags & MF_VOLDMANAGED; -} - -int fs_mgr_is_nonremovable(struct fstab_rec *fstab) -{ - return fstab->fs_mgr_flags & MF_NONREMOVABLE; -} - -int fs_mgr_is_encryptable(struct fstab_rec *fstab) -{ - return fstab->fs_mgr_flags & MF_CRYPT; -} - -int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab) -{ - return fstab->fs_mgr_flags & MF_NOEMULATEDSD; -} diff --git a/crypto/fs_mgr/fs_mgr_main.c b/crypto/fs_mgr/fs_mgr_main.c deleted file mode 100644 index 4bde4a1da..000000000 --- a/crypto/fs_mgr/fs_mgr_main.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2012 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 <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <libgen.h> -#include "fs_mgr_priv.h" - -char *me = ""; - -static void usage(void) -{ - ERROR("%s: usage: %s <-a | -n mnt_point blk_dev | -u> <fstab_file>\n", me, me); - exit(1); -} - -/* Parse the command line. If an error is encountered, print an error message - * and exit the program, do not return to the caller. - * Return the number of argv[] entries consumed. - */ -static void parse_options(int argc, char *argv[], int *a_flag, int *u_flag, int *n_flag, - char **n_name, char **n_blk_dev) -{ - me = basename(strdup(argv[0])); - - if (argc <= 1) { - usage(); - } - - if (!strcmp(argv[1], "-a")) { - if (argc != 3) { - usage(); - } - *a_flag = 1; - } - if (!strcmp(argv[1], "-n")) { - if (argc != 5) { - usage(); - } - *n_flag = 1; - *n_name = argv[2]; - *n_blk_dev = argv[3]; - } - if (!strcmp(argv[1], "-u")) { - if (argc != 3) { - usage(); - } - *u_flag = 1; - } - - /* If no flag is specified, it's an error */ - if (!(*a_flag | *n_flag | *u_flag)) { - usage(); - } - - /* If more than one flag is specified, it's an error */ - if ((*a_flag + *n_flag + *u_flag) > 1) { - usage(); - } - - return; -} - -int main(int argc, char *argv[]) -{ - int a_flag=0; - int u_flag=0; - int n_flag=0; - char *n_name; - char *n_blk_dev; - char *fstab_file; - struct fstab *fstab; - - klog_init(); - klog_set_level(6); - - parse_options(argc, argv, &a_flag, &u_flag, &n_flag, &n_name, &n_blk_dev); - - /* The name of the fstab file is last, after the option */ - fstab_file = argv[argc - 1]; - - fstab = fs_mgr_read_fstab(fstab_file); - - if (a_flag) { - return fs_mgr_mount_all(fstab); - } else if (n_flag) { - return fs_mgr_do_mount(fstab, n_name, n_blk_dev, 0); - } else if (u_flag) { - return fs_mgr_unmount_all(fstab); - } else { - ERROR("%s: Internal error, unknown option\n", me); - exit(1); - } - - fs_mgr_free_fstab(fstab); - - /* Should not get here */ - exit(1); -} - diff --git a/crypto/fs_mgr/fs_mgr_priv.h b/crypto/fs_mgr/fs_mgr_priv.h deleted file mode 100644 index 59ffd785c..000000000 --- a/crypto/fs_mgr/fs_mgr_priv.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#ifndef __CORE_FS_MGR_PRIV_H -#define __CORE_FS_MGR_PRIV_H - -#include <cutils/klog.h> -#include <fs_mgr.h> - -#define INFO(x...) KLOG_INFO("fs_mgr", x) -#define ERROR(x...) KLOG_ERROR("fs_mgr", x) - -#define CRYPTO_TMPFS_OPTIONS "size=128m,mode=0771,uid=1000,gid=1000" - -#define WAIT_TIMEOUT 20 - -/* fstab has the following format: - * - * Any line starting with a # is a comment and ignored - * - * Any blank line is ignored - * - * All other lines must be in this format: - * <source> <mount_point> <fs_type> <mount_flags> <fs_options> <fs_mgr_options> - * - * <mount_flags> is a comma separated list of flags that can be passed to the - * mount command. The list includes noatime, nosuid, nodev, nodiratime, - * ro, rw, remount, defaults. - * - * <fs_options> is a comma separated list of options accepted by the filesystem being - * mounted. It is passed directly to mount without being parsed - * - * <fs_mgr_options> is a comma separated list of flags that control the operation of - * the fs_mgr program. The list includes "wait", which will wait till - * the <source> file exists, and "check", which requests that the fs_mgr - * run an fscheck program on the <source> before mounting the filesystem. - * If check is specifed on a read-only filesystem, it is ignored. - * Also, "encryptable" means that filesystem can be encrypted. - * The "encryptable" flag _MUST_ be followed by a = and a string which - * is the location of the encryption keys. It can either be a path - * to a file or partition which contains the keys, or the word "footer" - * which means the keys are in the last 16 Kbytes of the partition - * containing the filesystem. - * - * When the fs_mgr is requested to mount all filesystems, it will first mount all the - * filesystems that do _NOT_ specify check (including filesystems that are read-only and - * specify check, because check is ignored in that case) and then it will check and mount - * filesystem marked with check. - * - */ - -#define MF_WAIT 0x1 -#define MF_CHECK 0x2 -#define MF_CRYPT 0x4 -#define MF_NONREMOVABLE 0x8 -#define MF_VOLDMANAGED 0x10 -#define MF_LENGTH 0x20 -#define MF_RECOVERYONLY 0x40 -#define MF_SWAPPRIO 0x80 -#define MF_ZRAMSIZE 0x100 -#define MF_VERIFY 0x200 -/* - * There is no emulated sdcard daemon running on /data/media on this device, - * so treat the physical SD card as the only external storage device, - * a la the Nexus One. - */ -#define MF_NOEMULATEDSD 0x400 - -#define DM_BUF_SIZE 4096 - -#endif /* __CORE_FS_MGR_PRIV_H */ - diff --git a/crypto/fs_mgr/fs_mgr_priv_verity.h b/crypto/fs_mgr/fs_mgr_priv_verity.h deleted file mode 100644 index 61937849a..000000000 --- a/crypto/fs_mgr/fs_mgr_priv_verity.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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. - */ - -int fs_mgr_setup_verity(struct fstab_rec *fstab);
\ No newline at end of file diff --git a/crypto/fs_mgr/fs_mgr_verity.c b/crypto/fs_mgr/fs_mgr_verity.c deleted file mode 100644 index 969eab2a0..000000000 --- a/crypto/fs_mgr/fs_mgr_verity.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <ctype.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <libgen.h> -#include <time.h> - -#include <private/android_filesystem_config.h> -#include <logwrap/logwrap.h> - -#include "mincrypt/rsa.h" -#include "mincrypt/sha.h" -#include "mincrypt/sha256.h" - -#include "ext4_utils.h" -#include "ext4.h" - -#include "fs_mgr_priv.h" -#include "fs_mgr_priv_verity.h" - -#define VERITY_METADATA_SIZE 32768 -#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001 -#define VERITY_TABLE_RSA_KEY "/verity_key" - -extern struct fs_info info; - -static RSAPublicKey *load_key(char *path) -{ - FILE *f; - RSAPublicKey *key; - - key = malloc(sizeof(RSAPublicKey)); - if (!key) { - ERROR("Can't malloc key\n"); - return NULL; - } - - f = fopen(path, "r"); - if (!f) { - ERROR("Can't open '%s'\n", path); - free(key); - return NULL; - } - - if (!fread(key, sizeof(*key), 1, f)) { - ERROR("Could not read key!"); - fclose(f); - free(key); - return NULL; - } - - if (key->len != RSANUMWORDS) { - ERROR("Invalid key length %d\n", key->len); - fclose(f); - free(key); - return NULL; - } - - fclose(f); - return key; -} - -static int verify_table(char *signature, char *table, int table_length) -{ - int fd; - RSAPublicKey *key; - uint8_t hash_buf[SHA_DIGEST_SIZE]; - int retval = -1; - - // Hash the table - SHA_hash((uint8_t*)table, table_length, hash_buf); - - // Now get the public key from the keyfile - key = load_key(VERITY_TABLE_RSA_KEY); - if (!key) { - ERROR("Couldn't load verity keys"); - goto out; - } - - // verify the result - if (!RSA_verify(key, - (uint8_t*) signature, - RSANUMBYTES, - (uint8_t*) hash_buf, - SHA_DIGEST_SIZE)) { - ERROR("Couldn't verify table."); - goto out; - } - - retval = 0; - -out: - free(key); - return retval; -} - -static int get_target_device_size(char *blk_device, uint64_t *device_size) -{ - int data_device; - struct ext4_super_block sb; - - data_device = open(blk_device, O_RDONLY); - if (data_device < 0) { - ERROR("Error opening block device (%s)", strerror(errno)); - return -1; - } - - if (lseek64(data_device, 1024, SEEK_SET) < 0) { - ERROR("Error seeking to superblock"); - close(data_device); - return -1; - } - - if (read(data_device, &sb, sizeof(sb)) != sizeof(sb)) { - ERROR("Error reading superblock"); - close(data_device); - return -1; - } - - ext4_parse_sb(&sb); - *device_size = info.len; - - close(data_device); - return 0; -} - -static int read_verity_metadata(char *block_device, char **signature, char **table) -{ - unsigned magic_number; - unsigned table_length; - uint64_t device_length; - int protocol_version; - FILE *device; - int retval = -1; - - device = fopen(block_device, "r"); - if (!device) { - ERROR("Could not open block device %s (%s).\n", block_device, strerror(errno)); - goto out; - } - - // find the start of the verity metadata - if (get_target_device_size(block_device, &device_length) < 0) { - ERROR("Could not get target device size.\n"); - goto out; - } - if (fseek(device, device_length, SEEK_SET) < 0) { - ERROR("Could not seek to start of verity metadata block.\n"); - goto out; - } - - // check the magic number - if (!fread(&magic_number, sizeof(int), 1, device)) { - ERROR("Couldn't read magic number!\n"); - goto out; - } - if (magic_number != VERITY_METADATA_MAGIC_NUMBER) { - ERROR("Couldn't find verity metadata at offset %llu!\n", device_length); - goto out; - } - - // check the protocol version - if (!fread(&protocol_version, sizeof(int), 1, device)) { - ERROR("Couldn't read verity metadata protocol version!\n"); - goto out; - } - if (protocol_version != 0) { - ERROR("Got unknown verity metadata protocol version %d!\n", protocol_version); - goto out; - } - - // get the signature - *signature = (char*) malloc(RSANUMBYTES * sizeof(char)); - if (!*signature) { - ERROR("Couldn't allocate memory for signature!\n"); - goto out; - } - if (!fread(*signature, RSANUMBYTES, 1, device)) { - ERROR("Couldn't read signature from verity metadata!\n"); - free(*signature); - goto out; - } - - // get the size of the table - if (!fread(&table_length, sizeof(int), 1, device)) { - ERROR("Couldn't get the size of the verity table from metadata!\n"); - free(*signature); - goto out; - } - - // get the table + null terminator - table_length += 1; - *table = malloc(table_length); - if(!*table) { - ERROR("Couldn't allocate memory for verity table!\n"); - goto out; - } - if (!fgets(*table, table_length, device)) { - ERROR("Couldn't read the verity table from metadata!\n"); - free(*table); - free(*signature); - goto out; - } - - retval = 0; - -out: - if (device) - fclose(device); - return retval; -} - -static void verity_ioctl_init(struct dm_ioctl *io, char *name, unsigned flags) -{ - memset(io, 0, DM_BUF_SIZE); - io->data_size = DM_BUF_SIZE; - io->data_start = sizeof(struct dm_ioctl); - io->version[0] = 4; - io->version[1] = 0; - io->version[2] = 0; - io->flags = flags | DM_READONLY_FLAG; - if (name) { - strlcpy(io->name, name, sizeof(io->name)); - } -} - -static int create_verity_device(struct dm_ioctl *io, char *name, int fd) -{ - verity_ioctl_init(io, name, 1); - if (ioctl(fd, DM_DEV_CREATE, io)) { - ERROR("Error creating device mapping (%s)", strerror(errno)); - return -1; - } - return 0; -} - -static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char **dev_name) -{ - verity_ioctl_init(io, name, 0); - if (ioctl(fd, DM_DEV_STATUS, io)) { - ERROR("Error fetching verity device number (%s)", strerror(errno)); - return -1; - } - int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); - if (asprintf(dev_name, "/dev/block/dm-%u", dev_num) < 0) { - ERROR("Error getting verity block device name (%s)", strerror(errno)); - return -1; - } - return 0; -} - -static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table) -{ - char *verity_params; - char *buffer = (char*) io; - uint64_t device_size = 0; - - if (get_target_device_size(blockdev, &device_size) < 0) { - return -1; - } - - verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG); - - struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; - - // set tgt arguments here - io->target_count = 1; - tgt->status=0; - tgt->sector_start=0; - tgt->length=device_size/512; - strcpy(tgt->target_type, "verity"); - - // build the verity params here - verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); - if (sprintf(verity_params, "%s", table) < 0) { - return -1; - } - - // set next target boundary - verity_params += strlen(verity_params) + 1; - verity_params = (char*) (((unsigned long)verity_params + 7) & ~8); - tgt->next = verity_params - buffer; - - // send the ioctl to load the verity table - if (ioctl(fd, DM_TABLE_LOAD, io)) { - ERROR("Error loading verity table (%s)", strerror(errno)); - return -1; - } - - return 0; -} - -static int resume_verity_table(struct dm_ioctl *io, char *name, int fd) -{ - verity_ioctl_init(io, name, 0); - if (ioctl(fd, DM_DEV_SUSPEND, io)) { - ERROR("Error activating verity device (%s)", strerror(errno)); - return -1; - } - return 0; -} - -static int test_access(char *device) { - int tries = 25; - while (tries--) { - if (!access(device, F_OK) || errno != ENOENT) { - return 0; - } - usleep(40 * 1000); - } - return -1; -} - -int fs_mgr_setup_verity(struct fstab_rec *fstab) { - - int retval = -1; - - char *verity_blk_name; - char *verity_table; - char *verity_table_signature; - - char buffer[DM_BUF_SIZE]; - struct dm_ioctl *io = (struct dm_ioctl *) buffer; - char *mount_point = basename(fstab->mount_point); - - // set the dm_ioctl flags - io->flags |= 1; - io->target_count = 1; - - // get the device mapper fd - int fd; - if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { - ERROR("Error opening device mapper (%s)", strerror(errno)); - return retval; - } - - // create the device - if (create_verity_device(io, mount_point, fd) < 0) { - ERROR("Couldn't create verity device!"); - goto out; - } - - // get the name of the device file - if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) { - ERROR("Couldn't get verity device number!"); - goto out; - } - - // read the verity block at the end of the block device - if (read_verity_metadata(fstab->blk_device, - &verity_table_signature, - &verity_table) < 0) { - goto out; - } - - // verify the signature on the table - if (verify_table(verity_table_signature, - verity_table, - strlen(verity_table)) < 0) { - goto out; - } - - // load the verity mapping table - if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table) < 0) { - goto out; - } - - // activate the device - if (resume_verity_table(io, mount_point, fd) < 0) { - goto out; - } - - // assign the new verity block device as the block device - free(fstab->blk_device); - fstab->blk_device = verity_blk_name; - - // make sure we've set everything up properly - if (test_access(fstab->blk_device) < 0) { - goto out; - } - - retval = 0; - -out: - close(fd); - return retval; -} diff --git a/crypto/fs_mgr/include/fs_mgr.h b/crypto/fs_mgr/include/fs_mgr.h deleted file mode 100644 index 0f90c32f1..000000000 --- a/crypto/fs_mgr/include/fs_mgr.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#ifndef __CORE_FS_MGR_H -#define __CORE_FS_MGR_H - -#include <stdint.h> -#include <linux/dm-ioctl.h> - -#ifdef __cplusplus -extern "C" { -#endif - -struct fstab { - int num_entries; - struct fstab_rec *recs; - char *fstab_filename; -}; - -struct fstab_rec { - char *blk_device; - char *mount_point; - char *fs_type; - unsigned long flags; - char *fs_options; - int fs_mgr_flags; - char *key_loc; - char *verity_loc; - long long length; - char *label; - int partnum; - int swap_prio; - unsigned int zram_size; -}; - -struct fstab *fs_mgr_read_fstab(const char *fstab_path); -void fs_mgr_free_fstab(struct fstab *fstab); -int fs_mgr_mount_all(struct fstab *fstab); -int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, - char *tmp_mount_point); -int fs_mgr_do_tmpfs_mount(char *n_name); -int fs_mgr_unmount_all(struct fstab *fstab); -int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, - char *real_blk_device, int size); -int fs_mgr_add_entry(struct fstab *fstab, - const char *mount_point, const char *fs_type, - const char *blk_device, long long length); -struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path); -int fs_mgr_is_voldmanaged(struct fstab_rec *fstab); -int fs_mgr_is_nonremovable(struct fstab_rec *fstab); -int fs_mgr_is_encryptable(struct fstab_rec *fstab); -int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab); -int fs_mgr_swapon_all(struct fstab *fstab); -#ifdef __cplusplus -} -#endif - -#endif /* __CORE_FS_MGR_H */ - diff --git a/crypto/ics/Android.mk b/crypto/ics/Android.mk deleted file mode 100644 index 5616c195a..000000000 --- a/crypto/ics/Android.mk +++ /dev/null @@ -1,25 +0,0 @@ -LOCAL_PATH := $(call my-dir) -ifeq ($(TW_INCLUDE_CRYPTO), true) -include $(CLEAR_VARS) - -LOCAL_MODULE := libcryptfsics -LOCAL_MODULE_TAGS := eng optional -LOCAL_CFLAGS := -LOCAL_CFLAGS += -DCRYPTO_FS_TYPE=\"$(TW_CRYPTO_FS_TYPE)\" -ifeq ($(TW_INCLUDE_CRYPTO_SAMSUNG), true) - LOCAL_CFLAGS += -DTW_INCLUDE_CRYPTO_SAMSUNG=\"$(TW_INCLUDE_CRYPTO_SAMSUNG)\" - LOCAL_LDFLAGS += -ldl - LOCAL_STATIC_LIBRARIES += libcrypt_samsung -endif -ifneq ($(TW_INTERNAL_STORAGE_PATH),) - LOCAL_CFLAGS += -DTW_INTERNAL_STORAGE_PATH=$(TW_INTERNAL_STORAGE_PATH) -endif -ifneq ($(TW_EXTERNAL_STORAGE_PATH),) - LOCAL_CFLAGS += -DTW_EXTERNAL_STORAGE_PATH=$(TW_EXTERNAL_STORAGE_PATH) -endif -LOCAL_SRC_FILES = cryptfs.c -LOCAL_C_INCLUDES += system/extras/ext4_utils external/openssl/include -LOCAL_SHARED_LIBRARIES += libc liblog libcutils libcrypto - -include $(BUILD_SHARED_LIBRARY) -endif diff --git a/crypto/ics/cryptfs.c b/crypto/ics/cryptfs.c deleted file mode 100644 index 4f3d5d01a..000000000 --- a/crypto/ics/cryptfs.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -/* TO DO: - * 1. Perhaps keep several copies of the encrypted key, in case something - * goes horribly wrong? - * - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdio.h> -#include <sys/ioctl.h> -#include <linux/dm-ioctl.h> -#include <libgen.h> -#include <stdlib.h> -#include <sys/param.h> -#include <string.h> -#include <sys/mount.h> -#include <openssl/evp.h> -#include <openssl/sha.h> -#include <errno.h> -#include <cutils/android_reboot.h> -#include <ext4.h> -#include <linux/kdev_t.h> -#include "cryptfs.h" -#define LOG_TAG "Cryptfs" -#include "cutils/log.h" -#include "cutils/properties.h" -#include "hardware_legacy/power.h" -//#include "VolumeManager.h" - -#define DM_CRYPT_BUF_SIZE 4096 -#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 - -#define KEY_LOC_PROP "ro.crypto.keyfile.userdata" -#define KEY_IN_FOOTER "footer" - -#define EXT4_FS 1 -#define FAT_FS 2 - -#ifndef EXPAND -#define STRINGIFY(x) #x -#define EXPAND(x) STRINGIFY(x) -#endif - -char *me = "cryptfs"; - -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]; -edk_payload_t edk_payload; -#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) -{ - memset(io, 0, dataSize); - io->data_size = dataSize; - io->data_start = sizeof(struct dm_ioctl); - io->version[0] = 4; - io->version[1] = 0; - io->version[2] = 0; - io->flags = flags; - if (name) { - strncpy(io->name, name, sizeof(io->name)); - } -} - -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; -} - -/* key or salt can be NULL, in which case just skip writing that value. Useful to - * update the failed mount count but not change the key. - */ -static int put_crypt_ftr_and_key(char *real_blk_name, struct crypt_mnt_ftr *crypt_ftr, - unsigned char *key, unsigned char *salt) -{ - // 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, - unsigned char *key, unsigned char *salt) -{ - int fd; - unsigned int nr_sec, cnt; - off64_t off; - int rc = -1; - char key_loc[PROPERTY_VALUE_MAX]; - char *fname; - 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_RDONLY)) < 0) { - printf("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) { - printf("Cannot seek to real block device footer\n"); - goto errout; - } - } else if (key_loc[0] == '/') { - fname = key_loc; - if ( (fd = open(fname, O_RDONLY)) < 0) { - printf("Cannot open footer file %s\n", fname); - return -1; - } - - /* Make sure it's 16 Kbytes in length */ - fstat(fd, &statbuf); - 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; - } - } else { - printf("Unexpected value for" KEY_LOC_PROP "\n"); - return -1;; - } - - if ( (cnt = read(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr))) != sizeof(struct crypt_mnt_ftr)) { - printf("Cannot read real block device footer\n"); - goto errout; - } - - 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; - if ( (cnt = read(fd, &edk_payload, sizeof(edk_payload_t))) != sizeof(edk_payload_t)) { - printf("Cannot read EDK payload from real block device footer\n"); - goto errout; - } - if (lseek64(fd, sizeof(__le32), SEEK_CUR) == -1) { - printf("Cannot seek past unknown data from real block device footer\n"); - goto errout; - } - memcpy(key, &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) { - printf("Cannot understand major version %d real block device footer\n", - crypt_ftr->major_version); - goto errout; - } - - if (crypt_ftr->minor_version != 0) { - printf("Warning: crypto footer minor version %d, expected 0, continuing...\n", - crypt_ftr->minor_version); - } - - if (crypt_ftr->ftr_size > sizeof(struct crypt_mnt_ftr)) { - /* the footer size is bigger than we expected. - * Skip to it's stated end so we can read the key. - */ - if (lseek64(fd, crypt_ftr->ftr_size - sizeof(struct crypt_mnt_ftr), SEEK_CUR) == -1) { - printf("Cannot seek to start of key\n"); - goto errout; - } - } - - 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; - } - - if ( (cnt = read(fd, key, crypt_ftr->keysize)) != crypt_ftr->keysize) { - printf("Cannot read key for real block device %s\n", fname); - goto errout; - } - - if (lseek64(fd, KEY_TO_SALT_PADDING, SEEK_CUR) == -1) { - printf("Cannot seek to real block device salt\n"); - goto errout; - } - - if ( (cnt = read(fd, salt, SALT_LEN)) != SALT_LEN) { - printf("Cannot read salt for real block device %s\n", fname); - goto errout; - } - - /* Success! */ - rc = 0; - -errout: - close(fd); - return rc; -} - -/* Convert a binary key of specified length into an ascii hex string equivalent, - * without the leading 0x and with null termination - */ -void convert_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'; - -} - -static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key, - 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 */ - char *crypt_params; - struct dm_ioctl *io; - struct dm_target_spec *tgt; - unsigned int minor; - int fd; - int retval = -1; - - if ((fd = open("/dev/device-mapper", O_RDWR)) < 0 ) { - printf("Cannot open device-mapper\n"); - goto errout; - } - - io = (struct dm_ioctl *) buffer; - - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - if (ioctl(fd, DM_DEV_CREATE, io)) { - printf("Cannot create dm-crypt device\n"); - goto errout; - } - - /* Get the device status, in particular, the name of it's device file */ - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - if (ioctl(fd, DM_DEV_STATUS, io)) { - printf("Cannot retrieve dm-crypt device status\n"); - goto errout; - } - minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); - snprintf(crypto_blk_name, MAXPATHLEN, "/dev/block/dm-%u", minor); - - /* Load the mapping table for this device */ - tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; - - ioctl_init(io, 4096, name, 0); - io->target_count = 1; - tgt->status = 0; - tgt->sector_start = 0; - tgt->length = crypt_ftr->fs_size; - strcpy(tgt->target_type, "crypt"); - - crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); - 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; - - if (ioctl(fd, DM_TABLE_LOAD, io)) { - printf("Cannot load dm-crypt mapping table.\n"); - goto errout; - } - - /* Resume this device to activate it */ - ioctl_init(io, 4096, name, 0); - - if (ioctl(fd, DM_DEV_SUSPEND, io)) { - printf("Cannot resume the dm-crypt device\n"); - goto errout; - } - - /* We made it here with no errors. Woot! */ - retval = 0; - -errout: - close(fd); /* If fd is <0 from a failed open call, it's safe to just ignore the close error */ - - return retval; -} - -static int delete_crypto_blk_dev(const char *name) -{ - int fd; - char buffer[DM_CRYPT_BUF_SIZE]; - struct dm_ioctl *io; - int retval = -1; - - if ((fd = open("/dev/device-mapper", O_RDWR)) < 0 ) { - printf("Cannot open device-mapper\n"); - goto errout; - } - - io = (struct dm_ioctl *) buffer; - - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - if (ioctl(fd, DM_DEV_REMOVE, io)) { - printf("Cannot remove dm-crypt device\n"); - goto errout; - } - - /* We made it here with no errors. Woot! */ - retval = 0; - -errout: - close(fd); /* If fd is <0 from a failed open call, it's safe to just ignore the close error */ - - return retval; - -} - -static void pbkdf2(char *passwd, unsigned char *salt, unsigned char *ikey) -{ - /* 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 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; - - /* Turn the password into a key and IV that can decrypt the master key */ - pbkdf2(passwd, salt, ikey); - - /* Initialize the decryption engine */ - if (! EVP_DecryptInit(&d_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) { - return -1; - } - EVP_CIPHER_CTX_set_padding(&d_ctx, 0); /* Turn off padding as our data is block aligned */ - /* Decrypt the master key */ - if (! EVP_DecryptUpdate(&d_ctx, decrypted_master_key, &decrypted_len, - encrypted_master_key, KEY_LEN_BYTES)) { - return -1; - } - if (! EVP_DecryptFinal(&d_ctx, decrypted_master_key + decrypted_len, &final_len)) { - return -1; - } - - if (decrypted_len + final_len != KEY_LEN_BYTES) { - return -1; - } else { - return 0; - } -} - -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]; - - property_get("ro.crypto.fs_type", fs_type, ""); - property_get("ro.crypto.fs_real_blkdev", real_blkdev, ""); - property_get("ro.crypto.fs_mnt_point", mount_point2, ""); - property_get("ro.crypto.fs_options", fs_options, ""); - property_get("ro.crypto.fs_flags", fs_flags, ""); - *mnt_flags = strtol(fs_flags, 0, 0); - - if (strcmp(mount_point, mount_point2)) { - /* Consistency check. These should match. If not, something odd happened. */ - return -1; - } - - return 0; -} - -static int get_orig_mount_parms_sd( - const char *mount_point, char *fs_type, char *real_blkdev) -{ - char mount_point2[PROPERTY_VALUE_MAX]; - - 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, ""); - - if (strcmp(mount_point, mount_point2)) { - /* Consistency check. These should match. If not, something odd happened. */ - return -1; - } - - return 0; -} - -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[256], 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]; - char tmp_mount_point[MAXPATHLEN]; - unsigned long mnt_flags; - unsigned int orig_failed_decrypt_count; - char encrypted_state[PROPERTY_VALUE_MAX]; - int rc; - - 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 %s\n", encrypted_state); - return -1; - } - - if (get_orig_mount_parms(mount_point, fs_type, real_blkdev, &mnt_flags, fs_options)) { - printf("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)) { - printf("Error getting crypt footer and key\n"); - return -1; - } - - //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)) { - printf("Error creating decrypted block device\n"); - return -1; - } - - /* If init detects an encrypted filesystme, it writes a file for each such - * encrypted fs into the tmpfs /data filesystem, and then the framework finds those - * files and passes that data to me */ - /* Create a tmp mount point to try mounting the decryptd fs - * Since we're here, the mount_point should be a tmpfs filesystem, so make - * a directory in it to test mount the decrypted filesystem. - */ - 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); - crypt_ftr.failed_decrypt_count++; - } else { - /* Success, so just umount and we'll mount it properly when we restart - * the framework. - */ - umount(tmp_mount_point); - crypt_ftr.failed_decrypt_count = 0; - } - - rmdir(tmp_mount_point); - - if (crypt_ftr.failed_decrypt_count) { - /* We failed to mount the device, so return an error */ - rc = crypt_ftr.failed_decrypt_count; - - } else { - /* Woot! Success! Save the name of the crypto block device - * so we can mount it when restarting the framework. - */ - property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev); - - /* 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, sizeof(saved_master_key)); - saved_data_blkdev = strdup(real_blkdev); - saved_mount_point = strdup(mount_point); - master_key_saved = 1; - rc = 0; - } - - return rc; -} - -static int test_mount_encrypted_fs_sd( - const char *passwd, const char *mount_point, const char *label) -{ - char real_blkdev[MAXPATHLEN]; - 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 ( !master_key_saved || strcmp(encrypted_state, "encrypted") ) { - printf("encrypted fs not yet validated or not running with encryption, aborting\n"); - return -1; - } - - 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; - } - - rc = cryptfs_setup_volume(label, real_blkdev, crypto_blkdev); - if(rc){ - printf("Error setting up cryptfs volume %s\n", real_blkdev); - return -1; - } - - 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 { - /* Success, so just umount and we'll mount it properly when we restart - * the framework. - */ - umount(tmp_mount_point); - - property_set("ro.crypto.sd_fs_crypto_blkdev", crypto_blkdev); - } - - rmdir(tmp_mount_point); - - return rc; -} - -/* - * 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) -{ - struct crypt_mnt_ftr sd_crypt_ftr; - unsigned char key[256], salt[32]; - struct stat statbuf; - int nr_sec, fd, rc; - - /* 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; - } - -#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"); - } - else if(!access("/efs/cryptprop_essiv", R_OK)){ - strcpy(sd_crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256"); - } - } -#endif - - sd_crypt_ftr.fs_size = nr_sec; - rc = create_crypto_blk_dev( - &sd_crypt_ftr, saved_master_key, real_blkdev, crypto_blkdev, label); - - stat(crypto_blkdev, &statbuf); - - return rc; -} - -int cryptfs_crypto_complete(void) -{ - return -1; -} - -int cryptfs_check_footer(void) -{ - int rc = -1; - char fs_type[PROPERTY_VALUE_MAX]; - char real_blkdev[MAXPATHLEN]; - char fs_options[PROPERTY_VALUE_MAX]; - unsigned long mnt_flags; - struct crypt_mnt_ftr crypt_ftr; - /* Allocate enough space for a 256 bit key, but we may use less */ - unsigned char encrypted_master_key[256]; - unsigned char salt[SALT_LEN]; - - if (get_orig_mount_parms(DATA_MNT_POINT, fs_type, real_blkdev, &mnt_flags, fs_options)) { - printf("Error reading original mount parms for mount point %s\n", DATA_MNT_POINT); - return rc; - } - - rc = get_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt); - - return rc; -} - -int cryptfs_check_passwd(const char *passwd) -{ - char pwbuf[256]; - char crypto_blkdev_data[MAXPATHLEN]; - int rc = -1; - - strcpy(pwbuf, passwd); - rc = test_mount_encrypted_fs(pwbuf, DATA_MNT_POINT, "userdata", crypto_blkdev_data); - -#ifdef TW_INCLUDE_CRYPTO_SAMSUNG - if(using_samsung_encryption) { - - int rc2 = 1; -#ifndef RECOVERY_SDCARD_ON_DATA -#ifdef TW_INTERNAL_STORAGE_PATH - // 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 -#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"); - // Mount the external storage as ecryptfs so that ecryptfs can act as a pass-through - if (!rc2 && strcmp(decrypt_external, "1") == 0) { - 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); - if (rc2 == 0) - property_set("ro.crypto.external_use_ecryptfs", "1"); - else - property_set("ro.crypto.external_use_ecryptfs", "0"); - } else { - printf("Unable to mount external storage with ecryptfs.\n"); - umount(EXPAND(TW_EXTERNAL_STORAGE_PATH)); - } - umount(DATA_MNT_POINT); - } -#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 deleted file mode 100644 index 8c8037659..000000000 --- a/crypto/ics/cryptfs.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -/* This structure starts 16,384 bytes before the end of a hardware - * partition that is encrypted. - * Immediately following this structure is the encrypted key. - * The keysize field tells how long the key is, in bytes. - * Then there is 32 bytes of padding, - * Finally there is the salt used with the user password. - * The salt is fixed at 16 bytes long. - * Obviously, the filesystem does not include the last 16 kbytes - * 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 - -#define SALT_LEN 16 -#define KEY_TO_SALT_PADDING 32 - -/* definitions of flags in the structure below */ -#define CRYPT_MNT_KEY_UNENCRYPTED 0x1 /* The key for the partition is not encrypted. */ -#define CRYPT_ENCRYPTION_IN_PROGRESS 0x2 /* 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; - __le16 minor_version; - __le32 ftr_size; /* in bytes, not including key following */ - __le32 flags; /* See above */ - __le32 keysize; /* in bytes */ - __le32 spare1; /* ignored */ - __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 */ - char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption - needed to decrypt this - partition, null terminated */ -}; - -#pragma pack() - - -#ifdef __cplusplus -extern "C" { -#endif - int cryptfs_check_footer(void); - int cryptfs_check_passwd(const char *pw); -#ifdef __cplusplus -} -#endif - -#endif // __CRYPTFS_H__ - diff --git a/crypto/jb/Android.mk b/crypto/jb/Android.mk deleted file mode 100644 index 90321d67e..000000000 --- a/crypto/jb/Android.mk +++ /dev/null @@ -1,17 +0,0 @@ -LOCAL_PATH := $(call my-dir) -ifeq ($(TW_INCLUDE_JB_CRYPTO), true) -include $(CLEAR_VARS) - -LOCAL_MODULE := libcryptfsjb -LOCAL_MODULE_TAGS := eng optional -LOCAL_CFLAGS := -LOCAL_SRC_FILES = cryptfs.c -LOCAL_C_INCLUDES += \ - system/extras/ext4_utils \ - external/openssl/include \ - $(commands_recovery_local_path)/crypto/scrypt/lib/crypto -LOCAL_SHARED_LIBRARIES += libc liblog libcutils libcrypto libext4_utils -LOCAL_STATIC_LIBRARIES += libfs_mgrtwrp libscrypttwrp_static liblogwraptwrp libmincrypttwrp - -include $(BUILD_SHARED_LIBRARY) -endif diff --git a/crypto/jb/cryptfs.c b/crypto/jb/cryptfs.c deleted file mode 100644 index f9c0d7489..000000000 --- a/crypto/jb/cryptfs.c +++ /dev/null @@ -1,1735 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -/* TO DO: - * 1. Perhaps keep several copies of the encrypted key, in case something - * goes horribly wrong? - * - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdio.h> -#include <sys/ioctl.h> -#include <linux/dm-ioctl.h> -#include <libgen.h> -#include <stdlib.h> -#include <sys/param.h> -#include <string.h> -#include <sys/mount.h> -#include <openssl/evp.h> -#include <openssl/sha.h> -#include <errno.h> -#include <ext4.h> -#include <linux/kdev_t.h> -#include <fs_mgr.h> -#include "cryptfs.h" -#define LOG_TAG "Cryptfs" -#include "cutils/log.h" -#include "cutils/properties.h" -#include "cutils/android_reboot.h" -#include "hardware_legacy/power.h" -/*#include <logwrap/logwrap.h> -#include "VolumeManager.h" -#include "VoldUtil.h"*/ -#include "crypto_scrypt.h" - -#define DM_CRYPT_BUF_SIZE 4096 -#define DATA_MNT_POINT "/data" - -#define HASH_COUNT 2000 -#define KEY_LEN_BYTES 16 -#define IV_LEN_BYTES 16 - -#define KEY_IN_FOOTER "footer" - -#define EXT4_FS 1 -#define FAT_FS 2 - -#define TABLE_LOAD_RETRIES 10 - -char *me = "cryptfs"; - -static unsigned char saved_master_key[KEY_LEN_BYTES]; -static char *saved_mount_point; -static int master_key_saved = 0; -static struct crypt_persist_data *persist_data = NULL; - -struct fstab *fstab; - -static void cryptfs_reboot(int recovery) -{ - /*if (recovery) { - property_set(ANDROID_RB_PROPERTY, "reboot,recovery"); - } else { - property_set(ANDROID_RB_PROPERTY, "reboot"); - } - sleep(20);*/ - - /* Shouldn't get here, reboot should happen before sleep times out */ - return; -} - -static void ioctl_init(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags) -{ - memset(io, 0, dataSize); - io->data_size = dataSize; - io->data_start = sizeof(struct dm_ioctl); - io->version[0] = 4; - io->version[1] = 0; - io->version[2] = 0; - io->flags = flags; - if (name) { - strncpy(io->name, name, sizeof(io->name)); - } -} - -/** - * 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 (i = 0, 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)) { - printf("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; - struct ext4_super_block sb; - off64_t len; - - if ((fd = open(dev, O_RDONLY)) < 0) { - printf("Cannot open device to get filesystem size "); - return 0; - } - - if (lseek64(fd, 1024, SEEK_SET) < 0) { - printf("Cannot seek to superblock"); - return 0; - } - - if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) { - printf("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; - - 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; - static off64_t cached_off = 0; - static char cached_metadata_fname[PROPERTY_VALUE_MAX] = ""; - int fd; - char key_loc[PROPERTY_VALUE_MAX]; - char real_blkdev[PROPERTY_VALUE_MAX]; - unsigned int nr_sec; - int rc = -1; - - if (!cached_data) { - fs_mgr_get_crypt_info(fstab, key_loc, real_blkdev, sizeof(key_loc)); - - if (!strcmp(key_loc, KEY_IN_FOOTER)) { - if ( (fd = open(real_blkdev, O_RDWR)) < 0) { - printf("Cannot open real block device %s\n", real_blkdev); - return -1; - } - - if ((nr_sec = get_blkdev_size(fd))) { - /* 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. - */ - strlcpy(cached_metadata_fname, real_blkdev, sizeof(cached_metadata_fname)); - cached_off = ((off64_t)nr_sec * 512) - CRYPT_FOOTER_OFFSET; - cached_data = 1; - } else { - printf("Cannot get size of block device %s\n", real_blkdev); - } - close(fd); - } else { - strlcpy(cached_metadata_fname, key_loc, sizeof(cached_metadata_fname)); - cached_off = 0; - cached_data = 1; - } - } - - if (cached_data) { - if (metadata_fname) { - *metadata_fname = cached_metadata_fname; - } - if (off) { - *off = cached_off; - } - rc = 0; - } - - return rc; -} - -/* key or salt can be NULL, in which case just skip writing that value. Useful to - * update the failed mount count but not change the key. - */ -static int put_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr) -{ - int fd; - unsigned int nr_sec, cnt; - /* starting_off is set to the SEEK_SET offset - * where the crypto structure starts - */ - off64_t starting_off; - int rc = -1; - char *fname = NULL; - struct stat statbuf; - - if (get_crypt_ftr_info(&fname, &starting_off)) { - printf("Unable to get crypt_ftr_info\n"); - return -1; - } - if (fname[0] != '/') { - printf("Unexpected value for crypto key location\n"); - return -1; - } - if ( (fd = open(fname, O_RDWR | O_CREAT, 0600)) < 0) { - printf("Cannot open footer file %s for put\n", fname); - return -1; - } - - /* Seek to the start of the crypt footer */ - if (lseek64(fd, starting_off, SEEK_SET) == -1) { - printf("Cannot seek to real block device footer\n"); - goto errout; - } - - if ((cnt = write(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr))) != sizeof(struct crypt_mnt_ftr)) { - printf("Cannot write real block device footer\n"); - 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)) { - if (ftruncate(fd, 0x4000)) { - printf("Cannot set footer file size\n", fname); - goto errout; - } - } - - /* Success! */ - rc = 0; - -errout: - close(fd); - return rc; - -} - -static inline int unix_read(int fd, void* buff, int len) -{ - return TEMP_FAILURE_RETRY(read(fd, buff, len)); -} - -static inline int unix_write(int fd, const void* buff, int len) -{ - return TEMP_FAILURE_RETRY(write(fd, buff, len)); -} - -static void init_empty_persist_data(struct crypt_persist_data *pdata, int len) -{ - memset(pdata, 0, len); - pdata->persist_magic = PERSIST_DATA_MAGIC; - pdata->persist_valid_entries = 0; -} - -/* A routine to update the passed in crypt_ftr to the lastest version. - * fd is open read/write on the device that holds the crypto footer and persistent - * data, crypt_ftr is a pointer to the struct to be updated, and offset is the - * absolute offset to the start of the crypt_mnt_ftr on the passed in fd. - */ -static void upgrade_crypt_ftr(int fd, struct crypt_mnt_ftr *crypt_ftr, off64_t offset) -{ - int orig_major = crypt_ftr->major_version; - int orig_minor = crypt_ftr->minor_version; - return; // in recovery we don't want to upgrade - 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; - - printf("upgrading crypto footer to 1.1"); - - pdata = malloc(CRYPT_PERSIST_DATA_SIZE); - if (pdata == NULL) { - printf("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) { - printf("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; - } - - if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version)) { - printf("upgrading crypto footer to 1.2"); - crypt_ftr->kdf_type = KDF_PBKDF2; - get_device_scrypt_params(crypt_ftr); - crypt_ftr->minor_version = 2; - } - - if ((orig_major != crypt_ftr->major_version) || (orig_minor != crypt_ftr->minor_version)) { - if (lseek64(fd, offset, SEEK_SET) == -1) { - printf("Cannot seek to crypt footer\n"); - return; - } - unix_write(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr)); - } -} - - -static int get_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr) -{ - int fd; - unsigned int nr_sec, cnt; - off64_t starting_off; - int rc = -1; - char *fname = NULL; - struct stat statbuf; - - if (get_crypt_ftr_info(&fname, &starting_off)) { - printf("Unable to get crypt_ftr_info\n"); - return -1; - } - if (fname[0] != '/') { - printf("Unexpected value for crypto key location\n"); - return -1; - } - if ( (fd = open(fname, O_RDWR)) < 0) { - printf("Cannot open footer file %s for get\n", fname); - return -1; - } - - /* Make sure it's 16 Kbytes in length */ - fstat(fd, &statbuf); - if (S_ISREG(statbuf.st_mode) && (statbuf.st_size != 0x4000)) { - printf("footer file %s is not the expected size!\n", fname); - goto errout; - } - - /* Seek to the start of the crypt footer */ - if (lseek64(fd, starting_off, SEEK_SET) == -1) { - printf("Cannot seek to real block device footer\n"); - goto errout; - } - - if ( (cnt = read(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr))) != sizeof(struct crypt_mnt_ftr)) { - printf("Cannot read real block device footer\n"); - goto errout; - } - - if (crypt_ftr->magic != CRYPT_MNT_MAGIC) { - printf("Bad magic for real block device %s\n", fname); - goto errout; - } - - if (crypt_ftr->major_version != CURRENT_MAJOR_VERSION) { - printf("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 > CURRENT_MINOR_VERSION) { - printf("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 < CURRENT_MINOR_VERSION) { - upgrade_crypt_ftr(fd, crypt_ftr, starting_off); - }*/ - - /* Success! */ - rc = 0; - -errout: - close(fd); - return rc; -} - -static int validate_persistent_data_storage(struct crypt_mnt_ftr *crypt_ftr) -{ - if (crypt_ftr->persist_data_offset[0] + crypt_ftr->persist_data_size > - crypt_ftr->persist_data_offset[1]) { - printf("Crypt_ftr persist data regions overlap"); - return -1; - } - - if (crypt_ftr->persist_data_offset[0] >= crypt_ftr->persist_data_offset[1]) { - printf("Crypt_ftr persist data region 0 starts after region 1"); - return -1; - } - - if (((crypt_ftr->persist_data_offset[1] + crypt_ftr->persist_data_size) - - (crypt_ftr->persist_data_offset[0] - CRYPT_FOOTER_TO_PERSIST_OFFSET)) > - CRYPT_FOOTER_OFFSET) { - printf("Persistent data extends past crypto footer"); - return -1; - } - - return 0; -} - -static int load_persistent_data(void) -{ - struct crypt_mnt_ftr crypt_ftr; - struct crypt_persist_data *pdata = NULL; - char encrypted_state[PROPERTY_VALUE_MAX]; - char *fname; - int found = 0; - int fd; - int ret; - int i; - - if (persist_data) { - /* Nothing to do, we've already loaded or initialized it */ - return 0; - } - - - /* If not encrypted, just allocate an empty table and initialize it */ - property_get("ro.crypto.state", encrypted_state, ""); - if (strcmp(encrypted_state, "encrypted") ) { - pdata = malloc(CRYPT_PERSIST_DATA_SIZE); - if (pdata) { - init_empty_persist_data(pdata, CRYPT_PERSIST_DATA_SIZE); - persist_data = pdata; - return 0; - } - return -1; - } - - if(get_crypt_ftr_and_key(&crypt_ftr)) { - return -1; - } - - if ((crypt_ftr.major_version != 1) || (crypt_ftr.minor_version != 1)) { - printf("Crypt_ftr version doesn't support persistent data"); - return -1; - } - - if (get_crypt_ftr_info(&fname, NULL)) { - return -1; - } - - ret = validate_persistent_data_storage(&crypt_ftr); - if (ret) { - return -1; - } - - fd = open(fname, O_RDONLY); - if (fd < 0) { - printf("Cannot open %s metadata file", fname); - return -1; - } - - if (persist_data == NULL) { - pdata = malloc(crypt_ftr.persist_data_size); - if (pdata == NULL) { - printf("Cannot allocate memory for persistent data"); - goto err; - } - } - - for (i = 0; i < 2; i++) { - if (lseek64(fd, crypt_ftr.persist_data_offset[i], SEEK_SET) < 0) { - printf("Cannot seek to read persistent data on %s", fname); - goto err2; - } - if (unix_read(fd, pdata, crypt_ftr.persist_data_size) < 0){ - printf("Error reading persistent data on iteration %d", i); - goto err2; - } - if (pdata->persist_magic == PERSIST_DATA_MAGIC) { - found = 1; - break; - } - } - - if (!found) { - printf("Could not find valid persistent data, creating"); - init_empty_persist_data(pdata, crypt_ftr.persist_data_size); - } - - /* Success */ - persist_data = pdata; - close(fd); - return 0; - -err2: - free(pdata); - -err: - close(fd); - return -1; -} - -static int save_persistent_data(void) -{ - struct crypt_mnt_ftr crypt_ftr; - struct crypt_persist_data *pdata; - char *fname; - off64_t write_offset; - off64_t erase_offset; - int found = 0; - int fd; - int ret; - - if (persist_data == NULL) { - printf("No persistent data to save"); - return -1; - } - - if(get_crypt_ftr_and_key(&crypt_ftr)) { - return -1; - } - - if ((crypt_ftr.major_version != 1) || (crypt_ftr.minor_version != 1)) { - printf("Crypt_ftr version doesn't support persistent data"); - return -1; - } - - ret = validate_persistent_data_storage(&crypt_ftr); - if (ret) { - return -1; - } - - if (get_crypt_ftr_info(&fname, NULL)) { - return -1; - } - - fd = open(fname, O_RDWR); - if (fd < 0) { - printf("Cannot open %s metadata file", fname); - return -1; - } - - pdata = malloc(crypt_ftr.persist_data_size); - if (pdata == NULL) { - printf("Cannot allocate persistant data"); - goto err; - } - - if (lseek64(fd, crypt_ftr.persist_data_offset[0], SEEK_SET) < 0) { - printf("Cannot seek to read persistent data on %s", fname); - goto err2; - } - - if (unix_read(fd, pdata, crypt_ftr.persist_data_size) < 0) { - printf("Error reading persistent data before save"); - goto err2; - } - - if (pdata->persist_magic == PERSIST_DATA_MAGIC) { - /* The first copy is the curent valid copy, so write to - * the second copy and erase this one */ - write_offset = crypt_ftr.persist_data_offset[1]; - erase_offset = crypt_ftr.persist_data_offset[0]; - } else { - /* The second copy must be the valid copy, so write to - * the first copy, and erase the second */ - write_offset = crypt_ftr.persist_data_offset[0]; - erase_offset = crypt_ftr.persist_data_offset[1]; - } - - /* Write the new copy first, if successful, then erase the old copy */ - if (lseek(fd, write_offset, SEEK_SET) < 0) { - printf("Cannot seek to write persistent data"); - goto err2; - } - if (unix_write(fd, persist_data, crypt_ftr.persist_data_size) == - (int) crypt_ftr.persist_data_size) { - if (lseek(fd, erase_offset, SEEK_SET) < 0) { - printf("Cannot seek to erase previous persistent data"); - goto err2; - } - fsync(fd); - memset(pdata, 0, crypt_ftr.persist_data_size); - if (unix_write(fd, pdata, crypt_ftr.persist_data_size) != - (int) crypt_ftr.persist_data_size) { - printf("Cannot write to erase previous persistent data"); - goto err2; - } - fsync(fd); - } else { - printf("Cannot write to save persistent data"); - goto err2; - } - - /* Success */ - free(pdata); - close(fd); - return 0; - -err2: - free(pdata); -err: - close(fd); - return -1; -} - -/* Convert a binary key of specified length into an ascii hex string equivalent, - * without the leading 0x and with null termination - */ -void convert_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'; - -} - -static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key, - char *real_blk_name, const char *name, int fd, - char *extra_params) -{ - char buffer[DM_CRYPT_BUF_SIZE]; - struct dm_ioctl *io; - struct dm_target_spec *tgt; - char *crypt_params; - char master_key_ascii[129]; /* Large enough to hold 512 bit key and null */ - int i; - - io = (struct dm_ioctl *) buffer; - - /* Load the mapping table for this device */ - tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; - - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - io->target_count = 1; - tgt->status = 0; - tgt->sector_start = 0; - tgt->length = crypt_ftr->fs_size; - strcpy(tgt->target_type, "crypt"); - - crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); - convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii); - sprintf(crypt_params, "%s %s 0 %s 0 %s", crypt_ftr->crypto_type_name, - master_key_ascii, real_blk_name, extra_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; - - for (i = 0; i < TABLE_LOAD_RETRIES; i++) { - if (! ioctl(fd, DM_TABLE_LOAD, io)) { - break; - } - usleep(500000); - } - - if (i == TABLE_LOAD_RETRIES) { - /* We failed to load the table, return an error */ - return -1; - } else { - return i + 1; - } -} - - -static int get_dm_crypt_version(int fd, const char *name, int *version) -{ - char buffer[DM_CRYPT_BUF_SIZE]; - struct dm_ioctl *io; - struct dm_target_versions *v; - int i; - - io = (struct dm_ioctl *) buffer; - - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - - if (ioctl(fd, DM_LIST_VERSIONS, io)) { - return -1; - } - - /* Iterate over the returned versions, looking for name of "crypt". - * When found, get and return the version. - */ - v = (struct dm_target_versions *) &buffer[sizeof(struct dm_ioctl)]; - while (v->next) { - if (! strcmp(v->name, "crypt")) { - /* We found the crypt driver, return the version, and get out */ - version[0] = v->version[0]; - version[1] = v->version[1]; - version[2] = v->version[2]; - return 0; - } - v = (struct dm_target_versions *)(((char *)v) + v->next); - } - - return -1; -} - -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) -{ - char buffer[DM_CRYPT_BUF_SIZE]; - char master_key_ascii[129]; /* Large enough to hold 512 bit key and null */ - char *crypt_params; - struct dm_ioctl *io; - struct dm_target_spec *tgt; - unsigned int minor; - int fd; - int i; - int retval = -1; - int version[3]; - char *extra_params; - int load_count; - - if ((fd = open("/dev/device-mapper", O_RDWR)) < 0 ) { - printf("Cannot open device-mapper\n"); - goto errout; - } - - io = (struct dm_ioctl *) buffer; - - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - if (ioctl(fd, DM_DEV_CREATE, io)) { - printf("Cannot create dm-crypt device\n"); - goto errout; - } - - /* Get the device status, in particular, the name of it's device file */ - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - if (ioctl(fd, DM_DEV_STATUS, io)) { - printf("Cannot retrieve dm-crypt device status\n"); - goto errout; - } - minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); - snprintf(crypto_blk_name, MAXPATHLEN, "/dev/block/dm-%u", minor); - - extra_params = ""; - if (! get_dm_crypt_version(fd, name, version)) { - /* Support for allow_discards was added in version 1.11.0 */ - if ((version[0] >= 2) || - ((version[0] == 1) && (version[1] >= 11))) { - extra_params = "1 allow_discards"; - printf("Enabling support for allow_discards in dmcrypt.\n"); - } - } - - load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name, - fd, extra_params); - if (load_count < 0) { - printf("Cannot load dm-crypt mapping table.\n"); - goto errout; - } else if (load_count > 1) { - printf("Took %d tries to load dmcrypt table.\n", load_count); - } - - /* Resume this device to activate it */ - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - - if (ioctl(fd, DM_DEV_SUSPEND, io)) { - printf("Cannot resume the dm-crypt device\n"); - goto errout; - } - - /* We made it here with no errors. Woot! */ - retval = 0; - -errout: - close(fd); /* If fd is <0 from a failed open call, it's safe to just ignore the close error */ - - return retval; -} - -static int delete_crypto_blk_dev(char *name) -{ - int fd; - char buffer[DM_CRYPT_BUF_SIZE]; - struct dm_ioctl *io; - int retval = -1; - - if ((fd = open("/dev/device-mapper", O_RDWR)) < 0 ) { - printf("Cannot open device-mapper\n"); - goto errout; - } - - io = (struct dm_ioctl *) buffer; - - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - if (ioctl(fd, DM_DEV_REMOVE, io)) { - printf("Cannot remove dm-crypt device\n"); - goto errout; - } - - /* We made it here with no errors. Woot! */ - retval = 0; - -errout: - close(fd); /* If fd is <0 from a failed open call, it's safe to just ignore the close error */ - - return retval; - -} - -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, - 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 */ - 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)) { - printf("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)) { - printf("EVP_EncryptUpdate failed\n"); - return -1; - } - if (! EVP_EncryptFinal(&e_ctx, encrypted_master_key + encrypted_len, &final_len)) { - printf("EVP_EncryptFinal failed\n"); - return -1; - } - - if (encrypted_len + final_len != KEY_LEN_BYTES) { - printf("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, - 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 */ - kdf(passwd, salt, ikey, kdf_params); - - /* Initialize the decryption engine */ - if (! EVP_DecryptInit(&d_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) { - return -1; - } - EVP_CIPHER_CTX_set_padding(&d_ctx, 0); /* Turn off padding as our data is block aligned */ - /* Decrypt the master key */ - if (! EVP_DecryptUpdate(&d_ctx, decrypted_master_key, &decrypted_len, - encrypted_master_key, KEY_LEN_BYTES)) { - return -1; - } - if (! EVP_DecryptFinal(&d_ctx, decrypted_master_key + decrypted_len, &final_len)) { - return -1; - } - - if (decrypted_len + final_len != KEY_LEN_BYTES) { - return -1; - } else { - return 0; - } -} - -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) { - printf("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; - 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, crypt_ftr); -} - -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) { - printf("unmounting %s succeeded\n", mountpoint); - rc = 0; - } else { - printf("unmounting %s failed\n", mountpoint); - rc = -1; - } - - return rc; -} - -#define DATA_PREP_TIMEOUT 200 -static int prep_data_fs(void) -{ - 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"); - printf("Just triggered post_fs_data\n"); - - /* Wait a max of 50 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. */ - printf("post_fs_data timed out!\n"); - return -1; - } else { - printf("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) { - printf("Encrypted filesystem not validated, aborting"); - return -1; - } - - if (restart_successful) { - printf("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. - */ - - /* 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"); - printf("Just asked init to shut down class main\n"); - - /* Ugh, shutting down the framework is not synchronous, so until it - * can be fixed, this horrible hack will wait a moment for it all to - * shut down before proceeding. Without it, some devices cannot - * restart the graphics services. - */ - sleep(2); - - /* 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) { - printf("fs_crypto_blkdev not set\n"); - return -1; - } - - if (! (rc = wait_and_unmount(DATA_MNT_POINT)) ) { - /* If that succeeded, then mount the decrypted filesystem */ - fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, 0); - - 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"); - printf("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; - char encrypted_state[PROPERTY_VALUE_MAX]; - char key_loc[PROPERTY_VALUE_MAX]; - - property_get("ro.crypto.state", encrypted_state, ""); - if (strcmp(encrypted_state, "encrypted") ) { - printf("not running with encryption, aborting"); - return 1; - } - - if (get_crypt_ftr_and_key(&crypt_ftr)) { - fs_mgr_get_crypt_info(fstab, key_loc, 0, sizeof(key_loc)); - - /* - * Only report this error if key_loc is a file and it exists. - * If the device was never encrypted, and /data is not mountable for - * some reason, returning 1 should prevent the UI from presenting the - * a "enter password" screen, or worse, a "press button to wipe the - * device" screen. - */ - if ((key_loc[0] == '/') && (access("key_loc", F_OK) == -1)) { - printf("master key file does not exist, aborting"); - return 1; - } else { - printf("Error getting crypt footer and key\n"); - return -1; - } - } - - if (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS) { - printf("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; -} - -static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) -{ - struct crypt_mnt_ftr crypt_ftr; - /* Allocate enough space for a 256 bit key, but we may use less */ - unsigned char decrypted_master_key[32]; - char crypto_blkdev[MAXPATHLEN]; - char real_blkdev[MAXPATHLEN]; - char tmp_mount_point[64]; - 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") ) { - printf("encrypted fs already validated or not running with encryption, aborting"); - return -1; - } - - fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev)); - - if (get_crypt_ftr_and_key(&crypt_ftr)) { - printf("Error getting crypt footer and key\n"); - return -1; - } - - 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_and_upgrade(passwd, decrypted_master_key, &crypt_ftr); - } - - if (create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, - real_blkdev, crypto_blkdev, label)) { - printf("Error creating decrypted block device\n"); - return -1; - } - - /* If init detects an encrypted filesystem, it writes a file for each such - * encrypted fs into the tmpfs /data filesystem, and then the framework finds those - * files and passes that data to me */ - /* Create a tmp mount point to try mounting the decryptd fs - * Since we're here, the mount_point should be a tmpfs filesystem, so make - * a directory in it to test mount the decrypted filesystem. - */ - sprintf(tmp_mount_point, "%s/tmp_mnt", mount_point); - mkdir(tmp_mount_point, 0755); - if (fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, tmp_mount_point)) { - printf("Error temp mounting decrypted block device\n"); - delete_crypto_blk_dev(label); - crypt_ftr.failed_decrypt_count++; - } else { - /* Success, so just umount and we'll mount it properly when we restart - * the framework. - */ - umount(tmp_mount_point); - crypt_ftr.failed_decrypt_count = 0; - } - - if (orig_failed_decrypt_count != crypt_ftr.failed_decrypt_count) { - put_crypt_ftr_and_key(&crypt_ftr); - } - - if (crypt_ftr.failed_decrypt_count) { - /* We failed to mount the device, so return an error */ - rc = crypt_ftr.failed_decrypt_count; - - } else { - /* Woot! Success! Save the name of the crypto block device - * so we can mount it when restarting the framework. - */ - property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev); - - /* 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); - saved_mount_point = strdup(mount_point); - master_key_saved = 1; - rc = 0; - } - - 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) -{ - 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; - struct stat statbuf; - int nr_sec, fd; - - sprintf(real_blkdev, "/dev/block/vold/%d:%d", major, minor); - - get_crypt_ftr_and_key(&sd_crypt_ftr); - - /* 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) { - printf("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"); -} - -#define FSTAB_PREFIX "/fstab." - -int cryptfs_check_footer(void) -{ - int rc = -1; - char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; - char propbuf[PROPERTY_VALUE_MAX]; - struct crypt_mnt_ftr crypt_ftr; - - property_get("ro.hardware", propbuf, ""); - snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); - - fstab = fs_mgr_read_fstab(fstab_filename); - if (!fstab) { - printf("failed to open %s\n", fstab_filename); - return -1; - } - - rc = get_crypt_ftr_and_key(&crypt_ftr); - - return rc; -} - -int cryptfs_check_passwd(char *passwd) -{ - int rc = -1; - char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; - char propbuf[PROPERTY_VALUE_MAX]; - - property_get("ro.hardware", propbuf, ""); - snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); - - fstab = fs_mgr_read_fstab(fstab_filename); - if (!fstab) { - printf("failed to open %s\n", fstab_filename); - return -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 decrypted_master_key[32]; - char encrypted_state[PROPERTY_VALUE_MAX]; - int rc; - - property_get("ro.crypto.state", encrypted_state, ""); - if (strcmp(encrypted_state, "encrypted") ) { - printf("device not encrypted, aborting"); - return -2; - } - - if (!master_key_saved) { - printf("encrypted fs not yet mounted, aborting"); - return -1; - } - - if (!saved_mount_point) { - printf("encrypted fs failed to save mount point, aborting"); - return -1; - } - - if (get_crypt_ftr_and_key(&crypt_ftr)) { - printf("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; - } else { - 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; - } else { - /* If incorrect, sleep for a bit to prevent dictionary attacks */ - sleep(1); - rc = 1; - } - } - - 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) -{ - off64_t off; - - memset(ftr, 0, sizeof(struct crypt_mnt_ftr)); - ftr->magic = CRYPT_MNT_MAGIC; - 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; - ftr->persist_data_offset[1] = off + CRYPT_FOOTER_TO_PERSIST_OFFSET + - ftr->persist_data_size; - } -} - -static int cryptfs_enable_wipe(char *crypto_blkdev, off64_t size, int type) -{ - return -1; -} - -#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) -{ - 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; - - if ( (realfd = open(real_blkdev, O_RDONLY)) < 0) { - printf("Error opening real_blkdev %s for inplace encrypt\n", real_blkdev); - return -1; - } - - if ( (cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) { - printf("Error opening crypto_blkdev %s for inplace encrypt\n", crypto_blkdev); - close(realfd); - 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; - - printf("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) { - printf("Error reading real_blkdev %s for inplace encrypt\n", crypto_blkdev); - goto errout; - } - if (unix_write(cryptofd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) { - printf("Error writing crypto_blkdev %s for inplace encrypt\n", crypto_blkdev); - goto errout; - } - } - - /* Do any remaining sectors */ - for (i=0; i<remainder; i++) { - if (unix_read(realfd, buf, 512) <= 0) { - printf("Error reading rival sectors from real_blkdev %s for inplace encrypt\n", crypto_blkdev); - goto errout; - } - if (unix_write(cryptofd, buf, 512) <= 0) { - printf("Error writing final sectors to crypto_blkdev %s for inplace encrypt\n", crypto_blkdev); - goto errout; - } - } - - *size_already_done += size; - rc = 0; - -errout: - close(realfd); - close(cryptofd); - - 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) -{ - return -1; -} - -int cryptfs_changepw(char *newpw) -{ - struct crypt_mnt_ftr crypt_ftr; - unsigned char decrypted_master_key[KEY_LEN_BYTES]; - - /* This is only allowed after we've successfully decrypted the master key */ - if (! master_key_saved) { - printf("Key not saved, aborting"); - return -1; - } - - /* get key */ - if (get_crypt_ftr_and_key(&crypt_ftr)) { - printf("Error getting crypt footer and key"); - return -1; - } - - 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); - - return 0; -} - -static int persist_get_key(char *fieldname, char *value) -{ - unsigned int i; - - if (persist_data == NULL) { - return -1; - } - for (i = 0; i < persist_data->persist_valid_entries; i++) { - if (!strncmp(persist_data->persist_entry[i].key, fieldname, PROPERTY_KEY_MAX)) { - /* We found it! */ - strlcpy(value, persist_data->persist_entry[i].val, PROPERTY_VALUE_MAX); - return 0; - } - } - - return -1; -} - -static int persist_set_key(char *fieldname, char *value, int encrypted) -{ - unsigned int i; - unsigned int num; - struct crypt_mnt_ftr crypt_ftr; - unsigned int max_persistent_entries; - unsigned int dsize; - - if (persist_data == NULL) { - return -1; - } - - /* If encrypted, use the values from the crypt_ftr, otherwise - * use the values for the current spec. - */ - if (encrypted) { - if(get_crypt_ftr_and_key(&crypt_ftr)) { - return -1; - } - dsize = crypt_ftr.persist_data_size; - } else { - dsize = CRYPT_PERSIST_DATA_SIZE; - } - max_persistent_entries = (dsize - sizeof(struct crypt_persist_data)) / - sizeof(struct crypt_persist_entry); - - num = persist_data->persist_valid_entries; - - for (i = 0; i < num; i++) { - if (!strncmp(persist_data->persist_entry[i].key, fieldname, PROPERTY_KEY_MAX)) { - /* We found an existing entry, update it! */ - memset(persist_data->persist_entry[i].val, 0, PROPERTY_VALUE_MAX); - strlcpy(persist_data->persist_entry[i].val, value, PROPERTY_VALUE_MAX); - return 0; - } - } - - /* We didn't find it, add it to the end, if there is room */ - if (persist_data->persist_valid_entries < max_persistent_entries) { - memset(&persist_data->persist_entry[num], 0, sizeof(struct crypt_persist_entry)); - strlcpy(persist_data->persist_entry[num].key, fieldname, PROPERTY_KEY_MAX); - strlcpy(persist_data->persist_entry[num].val, value, PROPERTY_VALUE_MAX); - persist_data->persist_valid_entries++; - return 0; - } - - return -1; -} - -/* Return the value of the specified field. */ -int cryptfs_getfield(char *fieldname, char *value, int len) -{ - char temp_value[PROPERTY_VALUE_MAX]; - char real_blkdev[MAXPATHLEN]; - /* 0 is success, 1 is not encrypted, - * -1 is value not set, -2 is any other error - */ - int rc = -2; - - if (persist_data == NULL) { - load_persistent_data(); - if (persist_data == NULL) { - printf("Getfield error, cannot load persistent data"); - goto out; - } - } - - if (!persist_get_key(fieldname, temp_value)) { - /* We found it, copy it to the caller's buffer and return */ - strlcpy(value, temp_value, len); - rc = 0; - } else { - /* Sadness, it's not there. Return the error */ - rc = -1; - } - -out: - return rc; -} - -/* Set the value of the specified field. */ -int cryptfs_setfield(char *fieldname, char *value) -{ - struct crypt_persist_data stored_pdata; - struct crypt_persist_data *pdata_p; - struct crypt_mnt_ftr crypt_ftr; - char encrypted_state[PROPERTY_VALUE_MAX]; - /* 0 is success, -1 is an error */ - int rc = -1; - int encrypted = 0; - - if (persist_data == NULL) { - load_persistent_data(); - if (persist_data == NULL) { - printf("Setfield error, cannot load persistent data"); - goto out; - } - } - - property_get("ro.crypto.state", encrypted_state, ""); - if (!strcmp(encrypted_state, "encrypted") ) { - encrypted = 1; - } - - if (persist_set_key(fieldname, value, encrypted)) { - goto out; - } - - /* If we are running encrypted, save the persistent data now */ - if (encrypted) { - if (save_persistent_data()) { - printf("Setfield error, cannot save persistent data"); - goto out; - } - } - - rc = 0; - -out: - return rc; -} diff --git a/crypto/jb/cryptfs.h b/crypto/jb/cryptfs.h deleted file mode 100644 index d815814d3..000000000 --- a/crypto/jb/cryptfs.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -/* This structure starts 16,384 bytes before the end of a hardware - * partition that is encrypted, or in a separate partition. It's location - * is specified by a property set in init.<device>.rc. - * The structure allocates 48 bytes for a key, but the real key size is - * specified in the struct. Currently, the code is hardcoded to use 128 - * bit keys. - * The fields after salt are only valid in rev 1.1 and later stuctures. - * Obviously, the filesystem does not include the last 16 kbytes - * of the partition if the crypt_mnt_ftr lives at the end of the - * partition. - */ - -#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 - -#define MAX_CRYPTO_TYPE_NAME_LEN 64 - -#define MAX_KEY_LEN 48 -#define SALT_LEN 16 - -/* definitions of flags in the structure below */ -#define CRYPT_MNT_KEY_UNENCRYPTED 0x1 /* The key for the partition is not encrypted. */ -#define CRYPT_ENCRYPTION_IN_PROGRESS 0x2 /* Set when starting encryption, - * clear when done before rebooting */ - -#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 __le8 unsigned char - -struct crypt_mnt_ftr { - __le32 magic; /* See above */ - __le16 major_version; - __le16 minor_version; - __le32 ftr_size; /* in bytes, not including key following */ - __le32 flags; /* See above */ - __le32 keysize; /* in bytes */ - __le32 spare1; /* ignored */ - __le64 fs_size; /* Size of the encrypted fs, in 512 byte sectors */ - __le32 failed_decrypt_count; /* count of # of failed attempts to decrypt and - mount, set to 0 on successful mount */ - unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption - needed to decrypt this - partition, null terminated */ - __le32 spare2; /* ignored */ - unsigned char master_key[MAX_KEY_LEN]; /* The encrypted key for decrypting the filesystem */ - unsigned char salt[SALT_LEN]; /* The salt used for this encryption */ - __le64 persist_data_offset[2]; /* Absolute offset to both copies of crypt_persist_data - * on device with that info, either the footer of the - * real_blkdevice or the metadata partition. */ - - __le32 persist_data_size; /* The number of bytes allocated to each copy of the - * persistent data table*/ - - __le8 kdf_type; /* The key derivation function used. */ - - /* scrypt parameters. See www.tarsnap.com/scrypt/scrypt.pdf */ - __le8 N_factor; /* (1 << N) */ - __le8 r_factor; /* (1 << r) */ - __le8 p_factor; /* (1 << p) */ -}; - -/* Persistant data that should be available before decryption. - * Things like airplane mode, locale and timezone are kept - * here and can be retrieved by the CryptKeeper UI to properly - * configure the phone before asking for the password - * This is only valid if the major and minor version above - * is set to 1.1 or higher. - * - * This is a 4K structure. There are 2 copies, and the code alternates - * writing one and then clearing the previous one. The reading - * code reads the first valid copy it finds, based on the magic number. - * The absolute offset to the first of the two copies is kept in rev 1.1 - * and higher crypt_mnt_ftr structures. - */ -struct crypt_persist_entry { - char key[PROPERTY_KEY_MAX]; - char val[PROPERTY_VALUE_MAX]; -}; - -/* Should be exactly 4K in size */ -struct crypt_persist_data { - __le32 persist_magic; - __le32 persist_valid_entries; - __le32 persist_spare[30]; - struct crypt_persist_entry persist_entry[0]; -}; - -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 -#define VOL_PRIMARY 0x4 -#define VOL_PROVIDES_ASEC 0x8 - -#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_footer(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_getfield(char *fieldname, char *value, int len); - int cryptfs_setfield(char *fieldname, char *value); -#ifdef __cplusplus -} -#endif - diff --git a/crypto/libcrypt_samsung/Android.mk b/crypto/libcrypt_samsung/Android.mk deleted file mode 100644 index 6e0e86903..000000000 --- a/crypto/libcrypt_samsung/Android.mk +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index 2fb6f2c4f..000000000 --- a/crypto/libcrypt_samsung/include/libcrypt_samsung.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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); - -typedef int (*unmount_ecryptfs_drive_t)( - const char *source); - -////////////////////////////////////////////////////////////////////////////// - -#endif // #ifndef __LIBCRYPT_SAMSUNG_H__ - -////////////////////////////////////////////////////////////////////////////// - diff --git a/crypto/libcrypt_samsung/libcrypt_samsung.c b/crypto/libcrypt_samsung/libcrypt_samsung.c deleted file mode 100644 index cd3a17804..000000000 --- a/crypto/libcrypt_samsung/libcrypt_samsung.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2013 a3955269 all rights reversed, no rights reserved. - */ - -////////////////////////////////////////////////////////////////////////////// - -#include <string.h> -#include <stdio.h> -#include <dlfcn.h> - -#include "include/libcrypt_samsung.h" - -////////////////////////////////////////////////////////////////////////////// - -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; -} - -int unmount_ecryptfs_drive( - const char *source) -{ - void *lib = dlopen("libsec_ecryptfs.so", RTLD_LAZY); - if(!lib) - return -100; - - int r = -101; - unmount_ecryptfs_drive_t sym = (unmount_ecryptfs_drive_t)dlsym(lib, "unmount_ecryptfs_drive"); - if(sym) - r = sym(source); - - dlclose(lib); - - return r; -}
\ No newline at end of file diff --git a/crypto/logwrapper/Android.mk b/crypto/logwrapper/Android.mk deleted file mode 100644 index 01b61930d..000000000 --- a/crypto/logwrapper/Android.mk +++ /dev/null @@ -1,34 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -# ======================================================== -# Static library -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE := liblogwraptwrp -LOCAL_SRC_FILES := logwrap.c -LOCAL_SHARED_LIBRARIES := libcutils liblog -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include -include $(BUILD_STATIC_LIBRARY) - -# ======================================================== -# Shared library -# ======================================================== -#include $(CLEAR_VARS) -#LOCAL_MODULE := liblogwrap -#LOCAL_SHARED_LIBRARIES := libcutils liblog -#LOCAL_WHOLE_STATIC_LIBRARIES := liblogwrap -#LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include -#LOCAL_C_INCLUDES := $(LOCAL_PATH)/include -#include $(BUILD_SHARED_LIBRARY) - -# ======================================================== -# Executable -# ======================================================== -#include $(CLEAR_VARS) -#LOCAL_SRC_FILES:= logwrapper.c -#LOCAL_MODULE := logwrapper -#LOCAL_STATIC_LIBRARIES := liblog liblogwrap libcutils -#include $(BUILD_EXECUTABLE) diff --git a/crypto/logwrapper/NOTICE b/crypto/logwrapper/NOTICE deleted file mode 100644 index c5b1efa7a..000000000 --- a/crypto/logwrapper/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/crypto/logwrapper/include/logwrap/logwrap.h b/crypto/logwrapper/include/logwrap/logwrap.h deleted file mode 100644 index 4307a3055..000000000 --- a/crypto/logwrapper/include/logwrap/logwrap.h +++ /dev/null @@ -1,87 +0,0 @@ -/* system/core/include/logwrap/logwrap.h - * - * Copyright 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. - */ - -#ifndef __LIBS_LOGWRAP_H -#define __LIBS_LOGWRAP_H - -#include <stdbool.h> - -__BEGIN_DECLS - -/* - * Run a command while logging its stdout and stderr - * - * WARNING: while this function is running it will clear all SIGCHLD handlers - * if you rely on SIGCHLD in the caller there is a chance zombies will be - * created if you're not calling waitpid after calling this. This function will - * log a warning when it clears SIGCHLD for processes other than the child it - * created. - * - * Arguments: - * argc: the number of elements in argv - * argv: an array of strings containing the command to be executed and its - * arguments as separate strings. argv does not need to be - * NULL-terminated - * status: the equivalent child status as populated by wait(status). This - * value is only valid when logwrap successfully completes. If NULL - * the return value of the child will be the function's return value. - * ignore_int_quit: set to true if you want to completely ignore SIGINT and - * SIGQUIT while logwrap is running. This may force the end-user to - * send a signal twice to signal the caller (once for the child, and - * once for the caller) - * log_target: Specify where to log the output of the child, either LOG_NONE, - * LOG_ALOG (for the Android system log), LOG_KLOG (for the kernel - * log), or LOG_FILE (and you need to specify a pathname in the - * file_path argument, otherwise pass NULL). These are bit fields, - * and can be OR'ed together to log to multiple places. - * abbreviated: If true, capture up to the first 100 lines and last 4K of - * output from the child. The abbreviated output is not dumped to - * the specified log until the child has exited. - * file_path: if log_target has the LOG_FILE bit set, then this parameter - * must be set to the pathname of the file to log to. - * - * Return value: - * 0 when logwrap successfully run the child process and captured its status - * -1 when an internal error occurred - * -ECHILD if status is NULL and the child didn't exit properly - * the return value of the child if it exited properly and status is NULL - * - */ - -/* Values for the log_target parameter android_fork_execvp_ext() */ -#define LOG_NONE 0 -#define LOG_ALOG 1 -#define LOG_KLOG 2 -#define LOG_FILE 4 - -int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit, - int log_target, bool abbreviated, char *file_path); - -/* Similar to above, except abbreviated logging is not available, and if logwrap - * is true, logging is to the Android system log, and if false, there is no - * logging. - */ -static inline int android_fork_execvp(int argc, char* argv[], int *status, - bool ignore_int_quit, bool logwrap) -{ - return android_fork_execvp_ext(argc, argv, status, ignore_int_quit, - (logwrap ? LOG_ALOG : LOG_NONE), false, NULL); -} - -__END_DECLS - -#endif /* __LIBS_LOGWRAP_H */ diff --git a/crypto/logwrapper/logwrap.c b/crypto/logwrapper/logwrap.c deleted file mode 100644 index 4ca1db4c8..000000000 --- a/crypto/logwrapper/logwrap.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (C) 2008 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 <string.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <poll.h> -#include <sys/wait.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <libgen.h> -#include <stdbool.h> -#include <pthread.h> - -#include <logwrap/logwrap.h> -#include "private/android_filesystem_config.h" -#include "cutils/log.h" -#include <cutils/klog.h> - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) -#define MIN(a,b) (((a)<(b))?(a):(b)) - -static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER; - -#define ERROR(fmt, args...) \ -do { \ - fprintf(stderr, fmt, ## args); \ - ALOG(LOG_ERROR, "logwrapper", fmt, ## args); \ -} while(0) - -#define FATAL_CHILD(fmt, args...) \ -do { \ - ERROR(fmt, ## args); \ - _exit(-1); \ -} while(0) - -#define MAX_KLOG_TAG 16 - -/* This is a simple buffer that holds up to the first beginning_buf->buf_size - * bytes of output from a command. - */ -#define BEGINNING_BUF_SIZE 0x1000 -struct beginning_buf { - char *buf; - size_t alloc_len; - /* buf_size is the usable space, which is one less than the allocated size */ - size_t buf_size; - size_t used_len; -}; - -/* This is a circular buf that holds up to the last ending_buf->buf_size bytes - * of output from a command after the first beginning_buf->buf_size bytes - * (which are held in beginning_buf above). - */ -#define ENDING_BUF_SIZE 0x1000 -struct ending_buf { - char *buf; - ssize_t alloc_len; - /* buf_size is the usable space, which is one less than the allocated size */ - ssize_t buf_size; - ssize_t used_len; - /* read and write offsets into the circular buffer */ - int read; - int write; -}; - - /* A structure to hold all the abbreviated buf data */ -struct abbr_buf { - struct beginning_buf b_buf; - struct ending_buf e_buf; - int beginning_buf_full; -}; - -/* Collect all the various bits of info needed for logging in one place. */ -struct log_info { - int log_target; - char klog_fmt[MAX_KLOG_TAG * 2]; - char *btag; - bool abbreviated; - FILE *fp; - struct abbr_buf a_buf; -}; - -/* Forware declaration */ -static void add_line_to_abbr_buf(struct abbr_buf *a_buf, char *linebuf, int linelen); - -/* Return 0 on success, and 1 when full */ -static int add_line_to_linear_buf(struct beginning_buf *b_buf, - char *line, ssize_t line_len) -{ - size_t new_len; - char *new_buf; - int full = 0; - - if ((line_len + b_buf->used_len) > b_buf->buf_size) { - full = 1; - } else { - /* Add to the end of the buf */ - memcpy(b_buf->buf + b_buf->used_len, line, line_len); - b_buf->used_len += line_len; - } - - return full; -} - -static void add_line_to_circular_buf(struct ending_buf *e_buf, - char *line, ssize_t line_len) -{ - ssize_t free_len; - ssize_t needed_space; - char *new_buf; - int cnt; - - if (e_buf->buf == NULL) { - return; - } - - if (line_len > e_buf->buf_size) { - return; - } - - free_len = e_buf->buf_size - e_buf->used_len; - - if (line_len > free_len) { - /* remove oldest entries at read, and move read to make - * room for the new string */ - needed_space = line_len - free_len; - e_buf->read = (e_buf->read + needed_space) % e_buf->buf_size; - e_buf->used_len -= needed_space; - } - - /* Copy the line into the circular buffer, dealing with possible - * wraparound. - */ - cnt = MIN(line_len, e_buf->buf_size - e_buf->write); - memcpy(e_buf->buf + e_buf->write, line, cnt); - if (cnt < line_len) { - memcpy(e_buf->buf, line + cnt, line_len - cnt); - } - e_buf->used_len += line_len; - e_buf->write = (e_buf->write + line_len) % e_buf->buf_size; -} - -/* Log directly to the specified log */ -static void do_log_line(struct log_info *log_info, char *line) { - if (log_info->log_target & LOG_KLOG) { - klog_write(6, log_info->klog_fmt, line); - } - if (log_info->log_target & LOG_ALOG) { - ALOG(LOG_INFO, log_info->btag, "%s", line); - } - if (log_info->log_target & LOG_FILE) { - fprintf(log_info->fp, "%s\n", line); - } -} - -/* Log to either the abbreviated buf, or directly to the specified log - * via do_log_line() above. - */ -static void log_line(struct log_info *log_info, char *line, int len) { - if (log_info->abbreviated) { - add_line_to_abbr_buf(&log_info->a_buf, line, len); - } else { - do_log_line(log_info, line); - } -} - -/* - * The kernel will take a maximum of 1024 bytes in any single write to - * the kernel logging device file, so find and print each line one at - * a time. The allocated size for buf should be at least 1 byte larger - * than buf_size (the usable size of the buffer) to make sure there is - * room to temporarily stuff a null byte to terminate a line for logging. - */ -static void print_buf_lines(struct log_info *log_info, char *buf, int buf_size) -{ - char *line_start; - char c; - int line_len; - int i; - - line_start = buf; - for (i = 0; i < buf_size; i++) { - if (*(buf + i) == '\n') { - /* Found a line ending, print the line and compute new line_start */ - /* Save the next char and replace with \0 */ - c = *(buf + i + 1); - *(buf + i + 1) = '\0'; - do_log_line(log_info, line_start); - /* Restore the saved char */ - *(buf + i + 1) = c; - line_start = buf + i + 1; - } else if (*(buf + i) == '\0') { - /* The end of the buffer, print the last bit */ - do_log_line(log_info, line_start); - break; - } - } - /* If the buffer was completely full, and didn't end with a newline, just - * ignore the partial last line. - */ -} - -static void init_abbr_buf(struct abbr_buf *a_buf) { - char *new_buf; - - memset(a_buf, 0, sizeof(struct abbr_buf)); - new_buf = malloc(BEGINNING_BUF_SIZE); - if (new_buf) { - a_buf->b_buf.buf = new_buf; - a_buf->b_buf.alloc_len = BEGINNING_BUF_SIZE; - a_buf->b_buf.buf_size = BEGINNING_BUF_SIZE - 1; - } - new_buf = malloc(ENDING_BUF_SIZE); - if (new_buf) { - a_buf->e_buf.buf = new_buf; - a_buf->e_buf.alloc_len = ENDING_BUF_SIZE; - a_buf->e_buf.buf_size = ENDING_BUF_SIZE - 1; - } -} - -static void free_abbr_buf(struct abbr_buf *a_buf) { - free(a_buf->b_buf.buf); - free(a_buf->e_buf.buf); -} - -static void add_line_to_abbr_buf(struct abbr_buf *a_buf, char *linebuf, int linelen) { - if (!a_buf->beginning_buf_full) { - a_buf->beginning_buf_full = - add_line_to_linear_buf(&a_buf->b_buf, linebuf, linelen); - } - if (a_buf->beginning_buf_full) { - add_line_to_circular_buf(&a_buf->e_buf, linebuf, linelen); - } -} - -static void print_abbr_buf(struct log_info *log_info) { - struct abbr_buf *a_buf = &log_info->a_buf; - - /* Add the abbreviated output to the kernel log */ - if (a_buf->b_buf.alloc_len) { - print_buf_lines(log_info, a_buf->b_buf.buf, a_buf->b_buf.used_len); - } - - /* Print an ellipsis to indicate that the buffer has wrapped or - * is full, and some data was not logged. - */ - if (a_buf->e_buf.used_len == a_buf->e_buf.buf_size) { - do_log_line(log_info, "...\n"); - } - - if (a_buf->e_buf.used_len == 0) { - return; - } - - /* Simplest way to print the circular buffer is allocate a second buf - * of the same size, and memcpy it so it's a simple linear buffer, - * and then cal print_buf_lines on it */ - if (a_buf->e_buf.read < a_buf->e_buf.write) { - /* no wrap around, just print it */ - print_buf_lines(log_info, a_buf->e_buf.buf + a_buf->e_buf.read, - a_buf->e_buf.used_len); - } else { - /* The circular buffer will always have at least 1 byte unused, - * so by allocating alloc_len here we will have at least - * 1 byte of space available as required by print_buf_lines(). - */ - char * nbuf = malloc(a_buf->e_buf.alloc_len); - if (!nbuf) { - return; - } - int first_chunk_len = a_buf->e_buf.buf_size - a_buf->e_buf.read; - memcpy(nbuf, a_buf->e_buf.buf + a_buf->e_buf.read, first_chunk_len); - /* copy second chunk */ - memcpy(nbuf + first_chunk_len, a_buf->e_buf.buf, a_buf->e_buf.write); - print_buf_lines(log_info, nbuf, first_chunk_len + a_buf->e_buf.write); - free(nbuf); - } -} - -static int parent(const char *tag, int parent_read, pid_t pid, - int *chld_sts, int log_target, bool abbreviated, char *file_path) { - int status = 0; - char buffer[4096]; - struct pollfd poll_fds[] = { - [0] = { - .fd = parent_read, - .events = POLLIN, - }, - }; - int rc = 0; - int fd; - - struct log_info log_info; - - int a = 0; // start index of unprocessed data - int b = 0; // end index of unprocessed data - int sz; - bool found_child = false; - char tmpbuf[256]; - - log_info.btag = basename(tag); - if (!log_info.btag) { - log_info.btag = (char*) tag; - } - - if (abbreviated && (log_target == LOG_NONE)) { - abbreviated = 0; - } - if (abbreviated) { - init_abbr_buf(&log_info.a_buf); - } - - if (log_target & LOG_KLOG) { - snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt), - "<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag); - } - - if ((log_target & LOG_FILE) && !file_path) { - /* No file_path specified, clear the LOG_FILE bit */ - log_target &= ~LOG_FILE; - } - - if (log_target & LOG_FILE) { - fd = open(file_path, O_WRONLY | O_CREAT, 0664); - if (fd < 0) { - ERROR("Cannot log to file %s\n", file_path); - log_target &= ~LOG_FILE; - } else { - lseek(fd, 0, SEEK_END); - log_info.fp = fdopen(fd, "a"); - } - } - - log_info.log_target = log_target; - log_info.abbreviated = abbreviated; - - while (!found_child) { - if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) { - ERROR("poll failed\n"); - rc = -1; - goto err_poll; - } - - if (poll_fds[0].revents & POLLIN) { - sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b); - - sz += b; - // Log one line at a time - for (b = 0; b < sz; b++) { - if (buffer[b] == '\r') { - if (abbreviated) { - /* The abbreviated logging code uses newline as - * the line separator. Lucikly, the pty layer - * helpfully cooks the output of the command - * being run and inserts a CR before NL. So - * I just change it to NL here when doing - * abbreviated logging. - */ - buffer[b] = '\n'; - } else { - buffer[b] = '\0'; - } - } else if (buffer[b] == '\n') { - buffer[b] = '\0'; - log_line(&log_info, &buffer[a], b - a); - a = b + 1; - } - } - - if (a == 0 && b == sizeof(buffer) - 1) { - // buffer is full, flush - buffer[b] = '\0'; - log_line(&log_info, &buffer[a], b - a); - b = 0; - } else if (a != b) { - // Keep left-overs - b -= a; - memmove(buffer, &buffer[a], b); - a = 0; - } else { - a = 0; - b = 0; - } - } - - if (poll_fds[0].revents & POLLHUP) { - int ret; - - ret = waitpid(pid, &status, WNOHANG); - if (ret < 0) { - rc = errno; - ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno)); - goto err_waitpid; - } - if (ret > 0) { - found_child = true; - } - } - } - - if (chld_sts != NULL) { - *chld_sts = status; - } else { - if (WIFEXITED(status)) - rc = WEXITSTATUS(status); - else - rc = -ECHILD; - } - - // Flush remaining data - if (a != b) { - buffer[b] = '\0'; - log_line(&log_info, &buffer[a], b - a); - } - - /* All the output has been processed, time to dump the abbreviated output */ - if (abbreviated) { - print_abbr_buf(&log_info); - } - - if (WIFEXITED(status)) { - if (WEXITSTATUS(status)) { - snprintf(tmpbuf, sizeof(tmpbuf), - "%s terminated by exit(%d)\n", log_info.btag, WEXITSTATUS(status)); - do_log_line(&log_info, tmpbuf); - } - } else { - if (WIFSIGNALED(status)) { - snprintf(tmpbuf, sizeof(tmpbuf), - "%s terminated by signal %d\n", log_info.btag, WTERMSIG(status)); - do_log_line(&log_info, tmpbuf); - } else if (WIFSTOPPED(status)) { - snprintf(tmpbuf, sizeof(tmpbuf), - "%s stopped by signal %d\n", log_info.btag, WSTOPSIG(status)); - do_log_line(&log_info, tmpbuf); - } - } - -err_waitpid: -err_poll: - if (log_target & LOG_FILE) { - fclose(log_info.fp); /* Also closes underlying fd */ - } - if (abbreviated) { - free_abbr_buf(&log_info.a_buf); - } - return rc; -} - -static void child(int argc, char* argv[]) { - // create null terminated argv_child array - char* argv_child[argc + 1]; - memcpy(argv_child, argv, argc * sizeof(char *)); - argv_child[argc] = NULL; - - if (execvp(argv_child[0], argv_child)) { - FATAL_CHILD("executing %s failed: %s\n", argv_child[0], - strerror(errno)); - } -} - -int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit, - int log_target, bool abbreviated, char *file_path) { - pid_t pid; - int parent_ptty; - int child_ptty; - char *child_devname = NULL; - struct sigaction intact; - struct sigaction quitact; - sigset_t blockset; - sigset_t oldset; - int rc = 0; - - rc = pthread_mutex_lock(&fd_mutex); - if (rc) { - ERROR("failed to lock signal_fd mutex\n"); - goto err_lock; - } - - /* Use ptty instead of socketpair so that STDOUT is not buffered */ - parent_ptty = open("/dev/ptmx", O_RDWR); - if (parent_ptty < 0) { - ERROR("Cannot create parent ptty\n"); - rc = -1; - goto err_open; - } - - if (grantpt(parent_ptty) || unlockpt(parent_ptty) || - ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { - ERROR("Problem with /dev/ptmx\n"); - rc = -1; - goto err_ptty; - } - - child_ptty = open(child_devname, O_RDWR); - if (child_ptty < 0) { - ERROR("Cannot open child_ptty\n"); - rc = -1; - goto err_child_ptty; - } - - sigemptyset(&blockset); - sigaddset(&blockset, SIGINT); - sigaddset(&blockset, SIGQUIT); - pthread_sigmask(SIG_BLOCK, &blockset, &oldset); - - pid = fork(); - if (pid < 0) { - close(child_ptty); - ERROR("Failed to fork\n"); - rc = -1; - goto err_fork; - } else if (pid == 0) { - pthread_mutex_unlock(&fd_mutex); - pthread_sigmask(SIG_SETMASK, &oldset, NULL); - close(parent_ptty); - - // redirect stdout and stderr - dup2(child_ptty, 1); - dup2(child_ptty, 2); - close(child_ptty); - - child(argc, argv); - } else { - close(child_ptty); - if (ignore_int_quit) { - struct sigaction ignact; - - memset(&ignact, 0, sizeof(ignact)); - ignact.sa_handler = SIG_IGN; - sigaction(SIGINT, &ignact, &intact); - sigaction(SIGQUIT, &ignact, &quitact); - } - - rc = parent(argv[0], parent_ptty, pid, status, log_target, - abbreviated, file_path); - } - - if (ignore_int_quit) { - sigaction(SIGINT, &intact, NULL); - sigaction(SIGQUIT, &quitact, NULL); - } -err_fork: - pthread_sigmask(SIG_SETMASK, &oldset, NULL); -err_child_ptty: -err_ptty: - close(parent_ptty); -err_open: - pthread_mutex_unlock(&fd_mutex); -err_lock: - return rc; -} diff --git a/crypto/logwrapper/logwrapper.c b/crypto/logwrapper/logwrapper.c deleted file mode 100644 index d0d8d1471..000000000 --- a/crypto/logwrapper/logwrapper.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008 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 <stdio.h> -#include <stdlib.h> -#include <sys/wait.h> -#include <unistd.h> - -#include <logwrap/logwrap.h> -#include <cutils/klog.h> - -#include "cutils/log.h" - -void fatal(const char *msg) { - fprintf(stderr, "%s", msg); - ALOG(LOG_ERROR, "logwrapper", "%s", msg); - exit(-1); -} - -void usage() { - fatal( - "Usage: logwrapper [-a] [-d] [-k] BINARY [ARGS ...]\n" - "\n" - "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n" - "the Android logging system. Tag is set to BINARY, priority is\n" - "always LOG_INFO.\n" - "\n" - "-a: Causes logwrapper to do abbreviated logging.\n" - " This logs up to the first 4K and last 4K of the command\n" - " being run, and logs the output when the command exits\n" - "-d: Causes logwrapper to SIGSEGV when BINARY terminates\n" - " fault address is set to the status of wait()\n" - "-k: Causes logwrapper to log to the kernel log instead of\n" - " the Android system log\n"); -} - -int main(int argc, char* argv[]) { - int seg_fault_on_exit = 0; - int log_target = LOG_ALOG; - bool abbreviated = false; - int ch; - int status = 0xAAAA; - int rc; - - while ((ch = getopt(argc, argv, "adk")) != -1) { - switch (ch) { - case 'a': - abbreviated = true; - break; - case 'd': - seg_fault_on_exit = 1; - break; - case 'k': - log_target = LOG_KLOG; - klog_set_level(6); - break; - case '?': - default: - usage(); - } - } - argc -= optind; - argv += optind; - - if (argc < 1) { - usage(); - } - - rc = android_fork_execvp_ext(argc, &argv[0], &status, true, - log_target, abbreviated, NULL); - if (!rc) { - if (WIFEXITED(status)) - rc = WEXITSTATUS(status); - else - rc = -ECHILD; - } - - if (seg_fault_on_exit) { - *(int *)status = 0; // causes SIGSEGV with fault_address = status - } - - return rc; -} diff --git a/crypto/lollipop/Android.mk b/crypto/lollipop/Android.mk index 40b4d5f95..da25eac30 100644 --- a/crypto/lollipop/Android.mk +++ b/crypto/lollipop/Android.mk @@ -21,16 +21,17 @@ common_shared_libraries := \ libcutils \ liblog \ libdiskconfig \ - libhardware_legacy \ liblogwrap \ libext4_utils \ libf2fs_sparseblock \ libcrypto \ libselinux \ libutils \ - libhardware \ + libminhardware \ libsoftkeymaster +common_shared_libraries := libcrypto libselinux libhardware libsoftkeymaster libcutils + LOCAL_MODULE := libcryptfslollipop LOCAL_MODULE_TAGS := eng optional LOCAL_CFLAGS := @@ -44,9 +45,26 @@ LOCAL_SRC_FILES = cryptfs.c # hardware/libhardware/include/hardware \ # system/security/softkeymaster/include/keymaster #LOCAL_SHARED_LIBRARIES += libc liblog libcutils libcrypto libext4_utils -LOCAL_SHARED_LIBRARIES := $(common_shared_libraries) libmincrypttwrp liblogwrap +LOCAL_SHARED_LIBRARIES := $(common_shared_libraries) libmincrypttwrp LOCAL_C_INCLUDES := external/openssl/include $(common_c_includes) -LOCAL_WHOLE_STATIC_LIBRARIES += libfs_mgr libscrypt_static +LOCAL_WHOLE_STATIC_LIBRARIES += libscrypttwrp_static + +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_SHARED_LIBRARIES := libcutils liblog + +LOCAL_INCLUDES += $(LOCAL_PATH) $(LOCAL_PATH)\libminhardware + +LOCAL_CFLAGS += -DQEMU_HARDWARE +QEMU_HARDWARE := true + +LOCAL_SHARED_LIBRARIES += libdl + +LOCAL_SRC_FILES += libminhardware/hardware.c + +LOCAL_MODULE:= libminhardware include $(BUILD_SHARED_LIBRARY) endif diff --git a/crypto/lollipop/cryptfs.c b/crypto/lollipop/cryptfs.c index 0277c78ef..90f1523d3 100644 --- a/crypto/lollipop/cryptfs.c +++ b/crypto/lollipop/cryptfs.c @@ -37,27 +37,17 @@ #include <sys/mount.h> #include <openssl/evp.h> #include <errno.h> -#include <ext4.h> #include <linux/kdev_t.h> -#include <fs_mgr.h> #include <time.h> #include "cryptfs.h" -#define LOG_TAG "Cryptfs" -#include "cutils/log.h" #include "cutils/properties.h" -#include "cutils/android_reboot.h" -#include "hardware_legacy/power.h" -#include <logwrap/logwrap.h> -//#include "VolumeManager.h" -//#include "VoldUtil.h" #include "crypto_scrypt.h" -#include "ext4_utils.h" -#include "f2fs_sparseblock.h" -//#include "CheckBattery.h" -//#include "Process.h" - #include <hardware/keymaster.h> +#ifndef min /* already defined by windows.h */ +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + #define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused)) @@ -91,6 +81,16 @@ static unsigned char saved_master_key[KEY_LEN_BYTES]; static char *saved_mount_point; static int master_key_saved = 0; static struct crypt_persist_data *persist_data = NULL; +static char key_fname[PROPERTY_VALUE_MAX] = ""; +static char real_blkdev[PROPERTY_VALUE_MAX] = ""; +static char file_system[PROPERTY_VALUE_MAX] = ""; + +void set_partition_data(const char* block_device, const char* key_location, const char* fs) +{ + strcpy(key_fname, key_location); + strcpy(real_blkdev, block_device); + strcpy(file_system, fs); +} static int keymaster_init(keymaster_device_t **keymaster_dev) { @@ -291,31 +291,6 @@ static char* password = 0; static int password_expiry_time = 0; static const int password_max_age_seconds = 60; -struct fstab *fstab; - -enum RebootType {reboot, recovery, shutdown}; -static void cryptfs_reboot(enum RebootType rt) -{ - switch(rt) { - case reboot: - property_set(ANDROID_RB_PROPERTY, "reboot"); - break; - - case recovery: - property_set(ANDROID_RB_PROPERTY, "reboot,recovery"); - break; - - case shutdown: - property_set(ANDROID_RB_PROPERTY, "shutdown"); - break; - } - - sleep(20); - - /* Shouldn't get here, reboot should happen before sleep times out */ - return; -} - static void ioctl_init(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags) { memset(io, 0, dataSize); @@ -380,41 +355,6 @@ static void get_device_scrypt_params(struct crypt_mnt_ftr *ftr) { ftr->p_factor = params[2]; } -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) { - printf("Cannot open device to get filesystem size "); - return 0; - } - - if (lseek64(fd, 1024, SEEK_SET) < 0) { - printf("Cannot seek to superblock"); - return 0; - } - - if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) { - printf("Cannot read superblock"); - return 0; - } - - close(fd); - - if (le32_to_cpu(sb.s_magic) != EXT4_SUPER_MAGIC) { - printf("Not a valid ext4 superblock"); - return 0; - } - 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; @@ -432,15 +372,12 @@ static int get_crypt_ftr_info(char **metadata_fname, off64_t *off) static off64_t cached_off = 0; static char cached_metadata_fname[PROPERTY_VALUE_MAX] = ""; int fd; - char key_loc[PROPERTY_VALUE_MAX]; - char real_blkdev[PROPERTY_VALUE_MAX]; unsigned int nr_sec; int rc = -1; if (!cached_data) { - fs_mgr_get_crypt_info(fstab, key_loc, real_blkdev, sizeof(key_loc)); - printf("get_crypt_ftr_info crypto key location: '%s'\n", key_loc); - if (!strcmp(key_loc, KEY_IN_FOOTER)) { + printf("get_crypt_ftr_info crypto key location: '%s'\n", key_fname); + if (!strcmp(key_fname, KEY_IN_FOOTER)) { if ( (fd = open(real_blkdev, O_RDWR)) < 0) { printf("Cannot open real block device %s\n", real_blkdev); return -1; @@ -459,7 +396,7 @@ static int get_crypt_ftr_info(char **metadata_fname, off64_t *off) } close(fd); } else { - strlcpy(cached_metadata_fname, key_loc, sizeof(cached_metadata_fname)); + strlcpy(cached_metadata_fname, key_fname, sizeof(cached_metadata_fname)); cached_off = 0; cached_data = 1; } @@ -478,65 +415,6 @@ static int get_crypt_ftr_info(char **metadata_fname, off64_t *off) return rc; } -/* key or salt can be NULL, in which case just skip writing that value. Useful to - * update the failed mount count but not change the key. - */ -static int put_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr) -{ - printf("TWRP NOT putting crypt footer and key\n"); - return 0; - int fd; - unsigned int nr_sec, cnt; - /* starting_off is set to the SEEK_SET offset - * where the crypto structure starts - */ - off64_t starting_off; - int rc = -1; - char *fname = NULL; - struct stat statbuf; - - if (get_crypt_ftr_info(&fname, &starting_off)) { - printf("Unable to get crypt_ftr_info\n"); - return -1; - } - if (fname[0] != '/') { - printf("Unexpected value for crypto key location\n"); - return -1; - } - if ( (fd = open(fname, O_RDWR | O_CREAT, 0600)) < 0) { - printf("Cannot open footer file %s for put\n", fname); - return -1; - } - - /* Seek to the start of the crypt footer */ - if (lseek64(fd, starting_off, SEEK_SET) == -1) { - printf("Cannot seek to real block device footer\n"); - goto errout; - } - - if ((cnt = write(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr))) != sizeof(struct crypt_mnt_ftr)) { - printf("Cannot write real block device footer\n"); - 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)) { - if (ftruncate(fd, 0x4000)) { - printf("Cannot set footer file size\n"); - goto errout; - } - } - - /* Success! */ - rc = 0; - -errout: - close(fd); - return rc; - -} - static inline int unix_read(int fd, void* buff, int len) { return TEMP_FAILURE_RETRY(read(fd, buff, len)); @@ -554,75 +432,6 @@ static void init_empty_persist_data(struct crypt_persist_data *pdata, int len) pdata->persist_valid_entries = 0; } -/* A routine to update the passed in crypt_ftr to the lastest version. - * fd is open read/write on the device that holds the crypto footer and persistent - * data, crypt_ftr is a pointer to the struct to be updated, and offset is the - * absolute offset to the start of the crypt_mnt_ftr on the passed in fd. - */ -static void upgrade_crypt_ftr(int fd, struct crypt_mnt_ftr *crypt_ftr, off64_t offset) -{ - int orig_major = crypt_ftr->major_version; - int orig_minor = crypt_ftr->minor_version; -printf("TWRP NOT upgrading crypto footer\n"); -return; // do not upgrade in recovery - 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; - - printf("upgrading crypto footer to 1.1"); - - pdata = malloc(CRYPT_PERSIST_DATA_SIZE); - if (pdata == NULL) { - printf("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) { - printf("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; - } - - if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 1)) { - printf("upgrading crypto footer to 1.2"); - /* But keep the old kdf_type. - * It will get updated later to KDF_SCRYPT after the password has been verified. - */ - crypt_ftr->kdf_type = KDF_PBKDF2; - get_device_scrypt_params(crypt_ftr); - crypt_ftr->minor_version = 2; - } - - if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 2)) { - printf("upgrading crypto footer to 1.3"); - crypt_ftr->crypt_type = CRYPT_TYPE_PASSWORD; - crypt_ftr->minor_version = 3; - } - - if ((orig_major != crypt_ftr->major_version) || (orig_minor != crypt_ftr->minor_version)) { - if (lseek64(fd, offset, SEEK_SET) == -1) { - printf("Cannot seek to crypt footer\n"); - return; - } - unix_write(fd, crypt_ftr, sizeof(struct crypt_mnt_ftr)); - } -} - - static int get_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr) { int fd; @@ -682,9 +491,9 @@ static int get_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr) /* 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 < CURRENT_MINOR_VERSION) { + /*if (crypt_ftr->minor_version < CURRENT_MINOR_VERSION) { upgrade_crypt_ftr(fd, crypt_ftr, starting_off); - } + }*/ /* Success! */ rc = 0; @@ -694,229 +503,6 @@ errout: return rc; } -static int validate_persistent_data_storage(struct crypt_mnt_ftr *crypt_ftr) -{ - if (crypt_ftr->persist_data_offset[0] + crypt_ftr->persist_data_size > - crypt_ftr->persist_data_offset[1]) { - printf("Crypt_ftr persist data regions overlap"); - return -1; - } - - if (crypt_ftr->persist_data_offset[0] >= crypt_ftr->persist_data_offset[1]) { - printf("Crypt_ftr persist data region 0 starts after region 1"); - return -1; - } - - if (((crypt_ftr->persist_data_offset[1] + crypt_ftr->persist_data_size) - - (crypt_ftr->persist_data_offset[0] - CRYPT_FOOTER_TO_PERSIST_OFFSET)) > - CRYPT_FOOTER_OFFSET) { - printf("Persistent data extends past crypto footer"); - return -1; - } - - return 0; -} - -static int load_persistent_data(void) -{ - struct crypt_mnt_ftr crypt_ftr; - struct crypt_persist_data *pdata = NULL; - char encrypted_state[PROPERTY_VALUE_MAX]; - char *fname; - int found = 0; - int fd; - int ret; - int i; - - if (persist_data) { - /* Nothing to do, we've already loaded or initialized it */ - return 0; - } - - - /* If not encrypted, just allocate an empty table and initialize it */ - property_get("ro.crypto.state", encrypted_state, ""); - if (strcmp(encrypted_state, "encrypted") ) { - pdata = malloc(CRYPT_PERSIST_DATA_SIZE); - if (pdata) { - init_empty_persist_data(pdata, CRYPT_PERSIST_DATA_SIZE); - persist_data = pdata; - return 0; - } - return -1; - } - - if(get_crypt_ftr_and_key(&crypt_ftr)) { - return -1; - } - - if ((crypt_ftr.major_version < 1) - || (crypt_ftr.major_version == 1 && crypt_ftr.minor_version < 1)) { - printf("Crypt_ftr version doesn't support persistent data"); - return -1; - } - - if (get_crypt_ftr_info(&fname, NULL)) { - return -1; - } - - ret = validate_persistent_data_storage(&crypt_ftr); - if (ret) { - return -1; - } - - fd = open(fname, O_RDONLY); - if (fd < 0) { - printf("Cannot open %s metadata file", fname); - return -1; - } - - if (persist_data == NULL) { - pdata = malloc(crypt_ftr.persist_data_size); - if (pdata == NULL) { - printf("Cannot allocate memory for persistent data"); - goto err; - } - } - - for (i = 0; i < 2; i++) { - if (lseek64(fd, crypt_ftr.persist_data_offset[i], SEEK_SET) < 0) { - printf("Cannot seek to read persistent data on %s", fname); - goto err2; - } - if (unix_read(fd, pdata, crypt_ftr.persist_data_size) < 0){ - printf("Error reading persistent data on iteration %d", i); - goto err2; - } - if (pdata->persist_magic == PERSIST_DATA_MAGIC) { - found = 1; - break; - } - } - - if (!found) { - printf("Could not find valid persistent data, creating"); - init_empty_persist_data(pdata, crypt_ftr.persist_data_size); - } - - /* Success */ - persist_data = pdata; - close(fd); - return 0; - -err2: - free(pdata); - -err: - close(fd); - return -1; -} - -static int save_persistent_data(void) -{ - struct crypt_mnt_ftr crypt_ftr; - struct crypt_persist_data *pdata; - char *fname; - off64_t write_offset; - off64_t erase_offset; - int found = 0; - int fd; - int ret; - - if (persist_data == NULL) { - printf("No persistent data to save"); - return -1; - } - - if(get_crypt_ftr_and_key(&crypt_ftr)) { - return -1; - } - - if ((crypt_ftr.major_version < 1) - || (crypt_ftr.major_version == 1 && crypt_ftr.minor_version < 1)) { - printf("Crypt_ftr version doesn't support persistent data"); - return -1; - } - - ret = validate_persistent_data_storage(&crypt_ftr); - if (ret) { - return -1; - } - - if (get_crypt_ftr_info(&fname, NULL)) { - return -1; - } - - fd = open(fname, O_RDWR); - if (fd < 0) { - printf("Cannot open %s metadata file", fname); - return -1; - } - - pdata = malloc(crypt_ftr.persist_data_size); - if (pdata == NULL) { - printf("Cannot allocate persistant data"); - goto err; - } - - if (lseek64(fd, crypt_ftr.persist_data_offset[0], SEEK_SET) < 0) { - printf("Cannot seek to read persistent data on %s", fname); - goto err2; - } - - if (unix_read(fd, pdata, crypt_ftr.persist_data_size) < 0) { - printf("Error reading persistent data before save"); - goto err2; - } - - if (pdata->persist_magic == PERSIST_DATA_MAGIC) { - /* The first copy is the curent valid copy, so write to - * the second copy and erase this one */ - write_offset = crypt_ftr.persist_data_offset[1]; - erase_offset = crypt_ftr.persist_data_offset[0]; - } else { - /* The second copy must be the valid copy, so write to - * the first copy, and erase the second */ - write_offset = crypt_ftr.persist_data_offset[0]; - erase_offset = crypt_ftr.persist_data_offset[1]; - } - - /* Write the new copy first, if successful, then erase the old copy */ - if (lseek(fd, write_offset, SEEK_SET) < 0) { - printf("Cannot seek to write persistent data"); - goto err2; - } - if (unix_write(fd, persist_data, crypt_ftr.persist_data_size) == - (int) crypt_ftr.persist_data_size) { - if (lseek(fd, erase_offset, SEEK_SET) < 0) { - printf("Cannot seek to erase previous persistent data"); - goto err2; - } - fsync(fd); - memset(pdata, 0, crypt_ftr.persist_data_size); - if (unix_write(fd, pdata, crypt_ftr.persist_data_size) != - (int) crypt_ftr.persist_data_size) { - printf("Cannot write to erase previous persistent data"); - goto err2; - } - fsync(fd); - } else { - printf("Cannot write to save persistent data"); - goto err2; - } - - /* Success */ - free(pdata); - close(fd); - return 0; - -err2: - free(pdata); -err: - close(fd); - return -1; -} - static int hexdigit (char c) { if (c >= '0' && c <= '9') return c - '0'; @@ -1424,321 +1010,12 @@ static int decrypt_master_key(char *passwd, unsigned char *decrypted_master_key, 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; - 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, crypt_ftr); -} - -static int wait_and_unmount(char *mountpoint, bool kill) -{ - int i, err, rc; -#define WAIT_UNMOUNT_COUNT 20 - - /* Now umount the tmpfs filesystem */ - for (i=0; i<WAIT_UNMOUNT_COUNT; i++) { - if (umount(mountpoint) == 0) { - break; - } - - 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; - } - - err = errno; - - /* If allowed, be increasingly aggressive before the last two retries */ - if (kill) { - if (i == (WAIT_UNMOUNT_COUNT - 3)) { - printf("sending SIGHUP to processes with open files\n"); - //vold_killProcessesWithOpenFiles(mountpoint, 1); - } else if (i == (WAIT_UNMOUNT_COUNT - 2)) { - printf("sending SIGKILL to processes with open files\n"); - //vold_killProcessesWithOpenFiles(mountpoint, 2); - } - } - - sleep(1); - } - - if (i < WAIT_UNMOUNT_COUNT) { - printf("unmounting %s succeeded\n", mountpoint); - rc = 0; - } else { - //vold_killProcessesWithOpenFiles(mountpoint, 0); - printf("unmounting %s failed: %s\n", mountpoint, strerror(err)); - rc = -1; - } - - return rc; -} - -#define DATA_PREP_TIMEOUT 200 -static int prep_data_fs(void) -{ - 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"); - printf("Just triggered post_fs_data\n"); - - /* Wait a max of 50 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. */ - printf("post_fs_data timed out!\n"); - return -1; - } else { - printf("post_fs_data done\n"); - return 0; - } -} - -static void cryptfs_set_corrupt() -{ - // Mark the footer as bad - struct crypt_mnt_ftr crypt_ftr; - if (get_crypt_ftr_and_key(&crypt_ftr)) { - printf("Failed to get crypto footer - panic"); - return; - } - - crypt_ftr.flags |= CRYPT_DATA_CORRUPT; - if (put_crypt_ftr_and_key(&crypt_ftr)) { - printf("Failed to set crypto footer - panic"); - return; - } -} - -static void cryptfs_trigger_restart_min_framework() -{ - if (fs_mgr_do_tmpfs_mount(DATA_MNT_POINT)) { - printf("Failed to mount tmpfs on data - panic"); - return; - } - - if (property_set("vold.decrypt", "trigger_post_fs_data")) { - printf("Failed to trigger post fs data - panic"); - return; - } - - if (property_set("vold.decrypt", "trigger_restart_min_framework")) { - printf("Failed to trigger restart min framework - panic"); - return; - } -} - -/* returns < 0 on failure */ -static int cryptfs_restart_internal(int restart_main) -{ - 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) { - printf("Encrypted filesystem not validated, aborting"); - return -1; - } - - if (restart_successful) { - printf("System already restarted with encrypted disk, aborting"); - return -1; - } - - if (restart_main) { - /* 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. - */ - - /* 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"); - printf("Just asked init to shut down class main\n"); - - /* Ugh, shutting down the framework is not synchronous, so until it - * can be fixed, this horrible hack will wait a moment for it all to - * shut down before proceeding. Without it, some devices cannot - * restart the graphics services. - */ - sleep(2); - } - - /* 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) { - printf("fs_crypto_blkdev not set\n"); - return -1; - } - - if (! (rc = wait_and_unmount(DATA_MNT_POINT, true)) ) { - /* If ro.crypto.readonly is set to 1, mount the decrypted - * filesystem readonly. This is used when /data is mounted by - * recovery mode. - */ - char ro_prop[PROPERTY_VALUE_MAX]; - property_get("ro.crypto.readonly", ro_prop, ""); - if (strlen(ro_prop) > 0 && atoi(ro_prop)) { - struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, DATA_MNT_POINT); - rec->flags |= MS_RDONLY; - } - - /* If that succeeded, then mount the decrypted filesystem */ - int retries = RETRY_MOUNT_ATTEMPTS; - int mount_rc; - while ((mount_rc = fs_mgr_do_mount(fstab, DATA_MNT_POINT, - crypto_blkdev, 0)) - != 0) { - if (mount_rc == FS_MGR_DOMNT_BUSY) { - /* TODO: invoke something similar to - Process::killProcessWithOpenFiles(DATA_MNT_POINT, - retries > RETRY_MOUNT_ATTEMPT/2 ? 1 : 2 ) */ - printf("Failed to mount %s because it is busy - waiting", - crypto_blkdev); - if (--retries) { - sleep(RETRY_MOUNT_DELAY_SECONDS); - } else { - /* Let's hope that a reboot clears away whatever is keeping - the mount busy */ - cryptfs_reboot(reboot); - } - } else { - printf("Failed to mount decrypted data"); - cryptfs_set_corrupt(); - cryptfs_trigger_restart_min_framework(); - printf("Started framework to offer wipe"); - return -1; - } - } - - 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"); - printf("Just triggered restart_framework\n"); - - /* Give it a few moments to get started */ - sleep(1); - } - - if (rc == 0) { - restart_successful = 1; - } - - return rc; -} - -int cryptfs_restart(void) -{ - /* Call internal implementation forcing a restart of main service group */ - return cryptfs_restart_internal(1); -} - -static int do_crypto_complete(char *mount_point UNUSED) -{ - struct crypt_mnt_ftr crypt_ftr; - char encrypted_state[PROPERTY_VALUE_MAX]; - char key_loc[PROPERTY_VALUE_MAX]; - - property_get("ro.crypto.state", encrypted_state, ""); - if (strcmp(encrypted_state, "encrypted") ) { - printf("not running with encryption, aborting"); - return CRYPTO_COMPLETE_NOT_ENCRYPTED; - } - - if (get_crypt_ftr_and_key(&crypt_ftr)) { - fs_mgr_get_crypt_info(fstab, key_loc, 0, sizeof(key_loc)); - - /* - * Only report this error if key_loc is a file and it exists. - * If the device was never encrypted, and /data is not mountable for - * some reason, returning 1 should prevent the UI from presenting the - * a "enter password" screen, or worse, a "press button to wipe the - * device" screen. - */ - if ((key_loc[0] == '/') && (access("key_loc", F_OK) == -1)) { - printf("master key file does not exist, aborting"); - return CRYPTO_COMPLETE_NOT_ENCRYPTED; - } else { - printf("Error getting crypt footer and key\n"); - return CRYPTO_COMPLETE_BAD_METADATA; - } - } - - // Test for possible error flags - if (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS){ - printf("Encryption process is partway completed\n"); - return CRYPTO_COMPLETE_PARTIAL; - } - - if (crypt_ftr.flags & CRYPT_INCONSISTENT_STATE){ - printf("Encryption process was interrupted but cannot continue\n"); - return CRYPTO_COMPLETE_INCONSISTENT; - } - - if (crypt_ftr.flags & CRYPT_DATA_CORRUPT){ - printf("Encryption is successful but data is corrupt\n"); - return CRYPTO_COMPLETE_CORRUPT; - } - - /* We passed the test! We shall diminish, and return to the west */ - return CRYPTO_COMPLETE_ENCRYPTED; -} - static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, char *passwd, char *mount_point, char *label) { /* Allocate enough space for a 256 bit key, but we may use less */ unsigned char decrypted_master_key[32]; char crypto_blkdev[MAXPATHLEN]; - char real_blkdev[MAXPATHLEN]; char tmp_mount_point[64]; unsigned int orig_failed_decrypt_count; int rc; @@ -1761,8 +1038,6 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, } } - fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev)); - // Create crypto block device - all (non fatal) code paths // need it if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key, @@ -1795,7 +1070,7 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, * the footer, not the key. */ sprintf(tmp_mount_point, "%s/tmp_mnt", mount_point); mkdir(tmp_mount_point, 0755); - if (fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, tmp_mount_point)) { + if (mount(crypto_blkdev, tmp_mount_point, file_system, NULL, NULL) != 0) { printf("Error temp mounting decrypted block device '%s'\n", crypto_blkdev); delete_crypto_blk_dev(label); @@ -1877,52 +1152,6 @@ int cryptfs_revert_volume(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; - struct stat statbuf; - int nr_sec, fd; - - sprintf(real_blkdev, "/dev/block/vold/%d:%d", major, minor); - - get_crypt_ftr_and_key(&sd_crypt_ftr); - - /* 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) { - printf("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 check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr) { char encrypted_state[PROPERTY_VALUE_MAX]; @@ -2034,24 +1263,11 @@ char* hexadj_passwd(const char* passwd) return hex; } -#define FSTAB_PREFIX "/fstab." - -int cryptfs_check_footer(void) +int cryptfs_check_footer() { int rc = -1; - char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; - char propbuf[PROPERTY_VALUE_MAX]; struct crypt_mnt_ftr crypt_ftr; - property_get("ro.hardware", propbuf, ""); - snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); - - fstab = fs_mgr_read_fstab(fstab_filename); - if (!fstab) { - printf("failed to open %s\n", fstab_filename); - return -1; - } - rc = get_crypt_ftr_and_key(&crypt_ftr); return rc; @@ -2061,17 +1277,6 @@ int cryptfs_check_passwd(char *passwd) { struct crypt_mnt_ftr crypt_ftr; int rc; - char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; - char propbuf[PROPERTY_VALUE_MAX]; - - property_get("ro.hardware", propbuf, ""); - snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); - - fstab = fs_mgr_read_fstab(fstab_filename); - if (!fstab) { - printf("failed to open %s\n", fstab_filename); - return -1; - } rc = check_unmounted_and_get_ftr(&crypt_ftr); if (rc) @@ -2223,1366 +1428,11 @@ static int cryptfs_init_crypt_mnt_ftr(struct crypt_mnt_ftr *ftr) return 0; } -static int cryptfs_enable_wipe(char *crypto_blkdev, off64_t size, int type) -{ - const char *args[10]; - char size_str[32]; /* Must be large enough to hold a %lld and null byte */ - int num_args; - int status; - int tmp; - int rc = -1; - - if (type == EXT4_FS) { - args[0] = "/system/bin/make_ext4fs"; - args[1] = "-a"; - args[2] = "/data"; - args[3] = "-l"; - snprintf(size_str, sizeof(size_str), "%" PRId64, size * 512); - args[4] = size_str; - args[5] = crypto_blkdev; - num_args = 6; - printf("Making empty filesystem with command %s %s %s %s %s %s\n", - args[0], args[1], args[2], args[3], args[4], args[5]); - } else if (type == F2FS_FS) { - args[0] = "/system/bin/mkfs.f2fs"; - args[1] = "-t"; - args[2] = "-d1"; - args[3] = crypto_blkdev; - snprintf(size_str, sizeof(size_str), "%" PRId64, size); - args[4] = size_str; - num_args = 5; - printf("Making empty filesystem with command %s %s %s %s %s\n", - args[0], args[1], args[2], args[3], args[4]); - } else { - printf("cryptfs_enable_wipe(): unknown filesystem type %d\n", type); - return -1; - } - - tmp = android_fork_execvp(num_args, (char **)args, &status, false, true); - - if (tmp != 0) { - printf("Error creating empty filesystem on %s due to logwrap error\n", crypto_blkdev); - } else { - if (WIFEXITED(status)) { - if (WEXITSTATUS(status)) { - printf("Error creating filesystem on %s, exit status %d ", - crypto_blkdev, WEXITSTATUS(status)); - } else { - printf("Successfully created filesystem on %s\n", crypto_blkdev); - rc = 0; - } - } else { - printf("Error creating filesystem on %s, did not exit normally\n", crypto_blkdev); - } - } - - return rc; -} - -#define CRYPT_INPLACE_BUFSIZE 4096 -#define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / CRYPT_SECTOR_SIZE) -#define CRYPT_SECTOR_SIZE 512 - -/* aligned 32K writes tends to make flash happy. - * SD card association recommends it. - */ -#define BLOCKS_AT_A_TIME 8 - -struct encryptGroupsData -{ - int realfd; - int cryptofd; - off64_t numblocks; - off64_t one_pct, cur_pct, new_pct; - off64_t blocks_already_done, tot_numblocks; - off64_t used_blocks_already_done, tot_used_blocks; - char* real_blkdev, * crypto_blkdev; - int count; - off64_t offset; - char* buffer; - off64_t last_written_sector; - int completed; - time_t time_started; - int remaining_time; -}; - -static void update_progress(struct encryptGroupsData* data, int is_used) -{ - data->blocks_already_done++; - - if (is_used) { - data->used_blocks_already_done++; - } - if (data->tot_used_blocks) { - data->new_pct = data->used_blocks_already_done / data->one_pct; - } else { - data->new_pct = data->blocks_already_done / data->one_pct; - } - - if (data->new_pct > data->cur_pct) { - char buf[8]; - data->cur_pct = data->new_pct; - snprintf(buf, sizeof(buf), "%" PRId64, data->cur_pct); - property_set("vold.encrypt_progress", buf); - } - - if (data->cur_pct >= 5) { - struct timespec time_now; - if (clock_gettime(CLOCK_MONOTONIC, &time_now)) { - printf("Error getting time"); - } else { - double elapsed_time = difftime(time_now.tv_sec, data->time_started); - off64_t remaining_blocks = data->tot_used_blocks - - data->used_blocks_already_done; - int remaining_time = (int)(elapsed_time * remaining_blocks - / data->used_blocks_already_done); - - // Change time only if not yet set, lower, or a lot higher for - // best user experience - if (data->remaining_time == -1 - || remaining_time < data->remaining_time - || remaining_time > data->remaining_time + 60) { - char buf[8]; - snprintf(buf, sizeof(buf), "%d", remaining_time); - property_set("vold.encrypt_time_remaining", buf); - data->remaining_time = remaining_time; - } - } - } -} - -static void log_progress(struct encryptGroupsData const* data, bool completed) -{ - // Precondition - if completed data = 0 else data != 0 - - // Track progress so we can skip logging blocks - static off64_t offset = -1; - - // Need to close existing 'Encrypting from' log? - if (completed || (offset != -1 && data->offset != offset)) { - printf("Encrypted to sector %" PRId64, - offset / info.block_size * CRYPT_SECTOR_SIZE); - offset = -1; - } - - // Need to start new 'Encrypting from' log? - if (!completed && offset != data->offset) { - printf("Encrypting from sector %" PRId64, - data->offset / info.block_size * CRYPT_SECTOR_SIZE); - } - - // Update offset - if (!completed) { - offset = data->offset + (off64_t)data->count * info.block_size; - } -} - -static int flush_outstanding_data(struct encryptGroupsData* data) -{ - if (data->count == 0) { - return 0; - } - - printf("Copying %d blocks at offset %" PRIx64, data->count, data->offset); - - if (pread64(data->realfd, data->buffer, - info.block_size * data->count, data->offset) - <= 0) { - printf("Error reading real_blkdev %s for inplace encrypt", - data->real_blkdev); - return -1; - } - - if (pwrite64(data->cryptofd, data->buffer, - info.block_size * data->count, data->offset) - <= 0) { - printf("Error writing crypto_blkdev %s for inplace encrypt", - data->crypto_blkdev); - return -1; - } else { - log_progress(data, false); - } - - data->count = 0; - data->last_written_sector = (data->offset + data->count) - / info.block_size * CRYPT_SECTOR_SIZE - 1; - return 0; -} - -static int encrypt_groups(struct encryptGroupsData* data) -{ - unsigned int i; - u8 *block_bitmap = 0; - unsigned int block; - off64_t ret; - int rc = -1; - - data->buffer = malloc(info.block_size * BLOCKS_AT_A_TIME); - if (!data->buffer) { - printf("Failed to allocate crypto buffer"); - goto errout; - } - - block_bitmap = malloc(info.block_size); - if (!block_bitmap) { - printf("failed to allocate block bitmap"); - goto errout; - } - - for (i = 0; i < aux_info.groups; ++i) { - printf("Encrypting group %d", i); - - u32 first_block = aux_info.first_data_block + i * info.blocks_per_group; - u32 block_count = min(info.blocks_per_group, - aux_info.len_blocks - first_block); - - off64_t offset = (u64)info.block_size - * aux_info.bg_desc[i].bg_block_bitmap; - - ret = pread64(data->realfd, block_bitmap, info.block_size, offset); - if (ret != (int)info.block_size) { - printf("failed to read all of block group bitmap %d", i); - goto errout; - } - - offset = (u64)info.block_size * first_block; - - data->count = 0; - - for (block = 0; block < block_count; block++) { - int used = bitmap_get_bit(block_bitmap, block); - update_progress(data, used); - if (used) { - if (data->count == 0) { - data->offset = offset; - } - data->count++; - } else { - if (flush_outstanding_data(data)) { - goto errout; - } - } - - offset += info.block_size; - - /* Write data if we are aligned or buffer size reached */ - if (offset % (info.block_size * BLOCKS_AT_A_TIME) == 0 - || data->count == BLOCKS_AT_A_TIME) { - if (flush_outstanding_data(data)) { - goto errout; - } - } - - if (1) { - printf("Stopping encryption due to low battery"); - rc = 0; - goto errout; - } - - } - if (flush_outstanding_data(data)) { - goto errout; - } - } - - data->completed = 1; - rc = 0; - -errout: - log_progress(0, true); - free(data->buffer); - free(block_bitmap); - return rc; -} - -static int cryptfs_enable_inplace_ext4(char *crypto_blkdev, - char *real_blkdev, - off64_t size, - off64_t *size_already_done, - off64_t tot_size, - off64_t previously_encrypted_upto) -{ - u32 i; - struct encryptGroupsData data; - int rc; // Can't initialize without causing warning -Wclobbered - - if (previously_encrypted_upto > *size_already_done) { - printf("Not fast encrypting since resuming part way through"); - return -1; - } - - memset(&data, 0, sizeof(data)); - data.real_blkdev = real_blkdev; - data.crypto_blkdev = crypto_blkdev; - - if ( (data.realfd = open(real_blkdev, O_RDWR)) < 0) { - printf("Error opening real_blkdev %s for inplace encrypt. err=%d(%s)\n", - real_blkdev, errno, strerror(errno)); - rc = -1; - goto errout; - } - - if ( (data.cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) { - printf("Error opening crypto_blkdev %s for ext4 inplace encrypt. err=%d(%s)\n", - crypto_blkdev, errno, strerror(errno)); - rc = ENABLE_INPLACE_ERR_DEV; - goto errout; - } - - if (setjmp(setjmp_env)) { - printf("Reading ext4 extent caused an exception\n"); - rc = -1; - goto errout; - } - - if (read_ext(data.realfd, 0) != 0) { - printf("Failed to read ext4 extent\n"); - rc = -1; - goto errout; - } - - data.numblocks = size / CRYPT_SECTORS_PER_BUFSIZE; - data.tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE; - data.blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE; - - printf("Encrypting ext4 filesystem in place..."); - - data.tot_used_blocks = data.numblocks; - for (i = 0; i < aux_info.groups; ++i) { - data.tot_used_blocks -= aux_info.bg_desc[i].bg_free_blocks_count; - } - - data.one_pct = data.tot_used_blocks / 100; - data.cur_pct = 0; - - struct timespec time_started = {0}; - if (clock_gettime(CLOCK_MONOTONIC, &time_started)) { - printf("Error getting time at start"); - // Note - continue anyway - we'll run with 0 - } - data.time_started = time_started.tv_sec; - data.remaining_time = -1; - - rc = encrypt_groups(&data); - if (rc) { - printf("Error encrypting groups"); - goto errout; - } - - *size_already_done += data.completed ? size : data.last_written_sector; - rc = 0; - -errout: - close(data.realfd); - close(data.cryptofd); - - return rc; -} - -static void log_progress_f2fs(u64 block, bool completed) -{ - // Precondition - if completed data = 0 else data != 0 - - // Track progress so we can skip logging blocks - static u64 last_block = (u64)-1; - - // Need to close existing 'Encrypting from' log? - if (completed || (last_block != (u64)-1 && block != last_block + 1)) { - printf("Encrypted to block %" PRId64, last_block); - last_block = -1; - } - - // Need to start new 'Encrypting from' log? - if (!completed && (last_block == (u64)-1 || block != last_block + 1)) { - printf("Encrypting from block %" PRId64, block); - } - - // Update offset - if (!completed) { - last_block = block; - } -} - -static int encrypt_one_block_f2fs(u64 pos, void *data) -{ - struct encryptGroupsData *priv_dat = (struct encryptGroupsData *)data; - - priv_dat->blocks_already_done = pos - 1; - update_progress(priv_dat, 1); - - off64_t offset = pos * CRYPT_INPLACE_BUFSIZE; - - if (pread64(priv_dat->realfd, priv_dat->buffer, CRYPT_INPLACE_BUFSIZE, offset) <= 0) { - printf("Error reading real_blkdev %s for f2fs inplace encrypt", priv_dat->crypto_blkdev); - return -1; - } - - if (pwrite64(priv_dat->cryptofd, priv_dat->buffer, CRYPT_INPLACE_BUFSIZE, offset) <= 0) { - printf("Error writing crypto_blkdev %s for f2fs inplace encrypt", priv_dat->crypto_blkdev); - return -1; - } else { - log_progress_f2fs(pos, false); - } - - return 0; -} - -static int cryptfs_enable_inplace_f2fs(char *crypto_blkdev, - char *real_blkdev, - off64_t size, - off64_t *size_already_done, - off64_t tot_size, - off64_t previously_encrypted_upto) -{ - u32 i; - struct encryptGroupsData data; - struct f2fs_info *f2fs_info = NULL; - int rc = ENABLE_INPLACE_ERR_OTHER; - if (previously_encrypted_upto > *size_already_done) { - printf("Not fast encrypting since resuming part way through"); - return ENABLE_INPLACE_ERR_OTHER; - } - memset(&data, 0, sizeof(data)); - data.real_blkdev = real_blkdev; - data.crypto_blkdev = crypto_blkdev; - data.realfd = -1; - data.cryptofd = -1; - if ( (data.realfd = open64(real_blkdev, O_RDWR)) < 0) { - printf("Error opening real_blkdev %s for f2fs inplace encrypt\n", - real_blkdev); - goto errout; - } - if ( (data.cryptofd = open64(crypto_blkdev, O_WRONLY)) < 0) { - printf("Error opening crypto_blkdev %s for f2fs inplace encrypt. err=%d(%s)\n", - crypto_blkdev, errno, strerror(errno)); - rc = ENABLE_INPLACE_ERR_DEV; - goto errout; - } - - f2fs_info = generate_f2fs_info(data.realfd); - if (!f2fs_info) - goto errout; - - data.numblocks = size / CRYPT_SECTORS_PER_BUFSIZE; - data.tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE; - data.blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE; - - data.tot_used_blocks = get_num_blocks_used(f2fs_info); - - data.one_pct = data.tot_used_blocks / 100; - data.cur_pct = 0; - data.time_started = time(NULL); - data.remaining_time = -1; - - data.buffer = malloc(f2fs_info->block_size); - if (!data.buffer) { - printf("Failed to allocate crypto buffer"); - goto errout; - } - - data.count = 0; - - /* Currently, this either runs to completion, or hits a nonrecoverable error */ - rc = run_on_used_blocks(data.blocks_already_done, f2fs_info, &encrypt_one_block_f2fs, &data); - - if (rc) { - printf("Error in running over f2fs blocks"); - rc = ENABLE_INPLACE_ERR_OTHER; - goto errout; - } - - *size_already_done += size; - rc = 0; - -errout: - if (rc) - printf("Failed to encrypt f2fs filesystem on %s", real_blkdev); - - log_progress_f2fs(0, true); - free(f2fs_info); - free(data.buffer); - close(data.realfd); - close(data.cryptofd); - - return rc; -} - -static int cryptfs_enable_inplace_full(char *crypto_blkdev, char *real_blkdev, - off64_t size, off64_t *size_already_done, - off64_t tot_size, - off64_t previously_encrypted_upto) -{ - int realfd, cryptofd; - char *buf[CRYPT_INPLACE_BUFSIZE]; - int rc = ENABLE_INPLACE_ERR_OTHER; - off64_t numblocks, i, remainder; - off64_t one_pct, cur_pct, new_pct; - off64_t blocks_already_done, tot_numblocks; - - if ( (realfd = open(real_blkdev, O_RDONLY)) < 0) { - printf("Error opening real_blkdev %s for inplace encrypt\n", real_blkdev); - return ENABLE_INPLACE_ERR_OTHER; - } - - if ( (cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) { - printf("Error opening crypto_blkdev %s for inplace encrypt. err=%d(%s)\n", - crypto_blkdev, errno, strerror(errno)); - close(realfd); - return ENABLE_INPLACE_ERR_DEV; - } - - /* 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; - - printf("Encrypting filesystem in place..."); - - i = previously_encrypted_upto + 1 - *size_already_done; - - if (lseek64(realfd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) { - printf("Cannot seek to previously encrypted point on %s", real_blkdev); - goto errout; - } - - if (lseek64(cryptofd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) { - printf("Cannot seek to previously encrypted point on %s", crypto_blkdev); - goto errout; - } - - for (;i < size && i % CRYPT_SECTORS_PER_BUFSIZE != 0; ++i) { - if (unix_read(realfd, buf, CRYPT_SECTOR_SIZE) <= 0) { - printf("Error reading initial sectors from real_blkdev %s for " - "inplace encrypt\n", crypto_blkdev); - goto errout; - } - if (unix_write(cryptofd, buf, CRYPT_SECTOR_SIZE) <= 0) { - printf("Error writing initial sectors to crypto_blkdev %s for " - "inplace encrypt\n", crypto_blkdev); - goto errout; - } else { - printf("Encrypted 1 block at %" PRId64, i); - } - } - - one_pct = tot_numblocks / 100; - cur_pct = 0; - /* process the majority of the filesystem in blocks */ - for (i/=CRYPT_SECTORS_PER_BUFSIZE; 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), "%" PRId64, cur_pct); - property_set("vold.encrypt_progress", buf); - } - if (unix_read(realfd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) { - printf("Error reading real_blkdev %s for inplace encrypt", crypto_blkdev); - goto errout; - } - if (unix_write(cryptofd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) { - printf("Error writing crypto_blkdev %s for inplace encrypt", crypto_blkdev); - goto errout; - } else { - printf("Encrypted %d block at %" PRId64, - CRYPT_SECTORS_PER_BUFSIZE, - i * CRYPT_SECTORS_PER_BUFSIZE); - } - - if (1) { - printf("Stopping encryption due to low battery"); - *size_already_done += (i + 1) * CRYPT_SECTORS_PER_BUFSIZE - 1; - rc = 0; - goto errout; - } - } - - /* Do any remaining sectors */ - for (i=0; i<remainder; i++) { - if (unix_read(realfd, buf, CRYPT_SECTOR_SIZE) <= 0) { - printf("Error reading final sectors from real_blkdev %s for inplace encrypt", crypto_blkdev); - goto errout; - } - if (unix_write(cryptofd, buf, CRYPT_SECTOR_SIZE) <= 0) { - printf("Error writing final sectors to crypto_blkdev %s for inplace encrypt", crypto_blkdev); - goto errout; - } else { - printf("Encrypted 1 block at next location"); - } - } - - *size_already_done += size; - rc = 0; - -errout: - close(realfd); - close(cryptofd); - - return rc; -} - -/* returns on of the ENABLE_INPLACE_* return codes */ -static int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev, - off64_t size, off64_t *size_already_done, - off64_t tot_size, - off64_t previously_encrypted_upto) -{ - int rc_ext4, rc_f2fs, rc_full; - if (previously_encrypted_upto) { - printf("Continuing encryption from %" PRId64, previously_encrypted_upto); - } - - if (*size_already_done + size < previously_encrypted_upto) { - *size_already_done += size; - return 0; - } - - /* TODO: identify filesystem type. - * As is, cryptfs_enable_inplace_ext4 will fail on an f2fs partition, and - * then we will drop down to cryptfs_enable_inplace_f2fs. - * */ - if ((rc_ext4 = cryptfs_enable_inplace_ext4(crypto_blkdev, real_blkdev, - size, size_already_done, - tot_size, previously_encrypted_upto)) == 0) { - return 0; - } - printf("cryptfs_enable_inplace_ext4()=%d\n", rc_ext4); - - if ((rc_f2fs = cryptfs_enable_inplace_f2fs(crypto_blkdev, real_blkdev, - size, size_already_done, - tot_size, previously_encrypted_upto)) == 0) { - return 0; - } - printf("cryptfs_enable_inplace_f2fs()=%d\n", rc_f2fs); - - rc_full = cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev, - size, size_already_done, tot_size, - previously_encrypted_upto); - printf("cryptfs_enable_inplace_full()=%d\n", rc_full); - - /* Hack for b/17898962, the following is the symptom... */ - if (rc_ext4 == ENABLE_INPLACE_ERR_DEV - && rc_f2fs == ENABLE_INPLACE_ERR_DEV - && rc_full == ENABLE_INPLACE_ERR_DEV) { - return ENABLE_INPLACE_ERR_DEV; - } - return rc_full; -} - -#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); -} - -static int cryptfs_SHA256_fileblock(const char* filename, __le8* buf) -{ - int fd = open(filename, O_RDONLY); - if (fd == -1) { - printf("Error opening file %s", filename); - return -1; - } - - char block[CRYPT_INPLACE_BUFSIZE]; - memset(block, 0, sizeof(block)); - if (unix_read(fd, block, sizeof(block)) < 0) { - printf("Error reading file %s", filename); - close(fd); - return -1; - } - - close(fd); - - SHA256_CTX c; - SHA256_Init(&c); - SHA256_Update(&c, block, sizeof(block)); - SHA256_Final(buf, &c); - - return 0; -} - -static int get_fs_type(struct fstab_rec *rec) -{ - if (!strcmp(rec->fs_type, "ext4")) { - return EXT4_FS; - } else if (!strcmp(rec->fs_type, "f2fs")) { - return F2FS_FS; - } else { - return -1; - } -} - -static int cryptfs_enable_all_volumes(struct crypt_mnt_ftr *crypt_ftr, int how, - char *crypto_blkdev, char *real_blkdev, - int previously_encrypted_upto) -{ - off64_t cur_encryption_done=0, tot_encryption_size=0; - int i, rc = -1; - - if (1) { - printf("Not starting encryption due to low battery"); - return 0; - } - - /* The size of the userdata partition, and add in the vold volumes below */ - tot_encryption_size = crypt_ftr->fs_size; - - if (how == CRYPTO_ENABLE_WIPE) { - struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, DATA_MNT_POINT); - int fs_type = get_fs_type(rec); - if (fs_type < 0) { - printf("cryptfs_enable: unsupported fs type %s\n", rec->fs_type); - return -1; - } - rc = cryptfs_enable_wipe(crypto_blkdev, crypt_ftr->fs_size, fs_type); - } else if (how == CRYPTO_ENABLE_INPLACE) { - rc = cryptfs_enable_inplace(crypto_blkdev, real_blkdev, - crypt_ftr->fs_size, &cur_encryption_done, - tot_encryption_size, - previously_encrypted_upto); - - if (rc == ENABLE_INPLACE_ERR_DEV) { - /* Hack for b/17898962 */ - printf("cryptfs_enable: crypto block dev failure. Must reboot...\n"); - cryptfs_reboot(reboot); - } - - if (!rc) { - crypt_ftr->encrypted_upto = cur_encryption_done; - } - - if (!rc && crypt_ftr->encrypted_upto == crypt_ftr->fs_size) { - /* The inplace routine never actually sets the progress to 100% due - * to the round down nature of integer division, so set it here */ - property_set("vold.encrypt_progress", "100"); - } - } else { - /* Shouldn't happen */ - printf("cryptfs_enable: internal error, unknown option\n"); - rc = -1; - } - - return rc; -} - -int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd, - int allow_reboot) -{ - int how = 0; - char crypto_blkdev[MAXPATHLEN], real_blkdev[MAXPATHLEN]; - unsigned long nr_sec; - unsigned char decrypted_master_key[KEY_LEN_BYTES]; - int rc=-1, fd, i, ret; - struct crypt_mnt_ftr crypt_ftr; - struct crypt_persist_data *pdata; - char encrypted_state[PROPERTY_VALUE_MAX]; - char lockid[32] = { 0 }; - char key_loc[PROPERTY_VALUE_MAX]; - char fuse_sdcard[PROPERTY_VALUE_MAX]; - char *sd_mnt_point; - int num_vols; - struct volume_info *vol_list = 0; - off64_t previously_encrypted_upto = 0; -printf("cryptfs_enable_internal disabled by TWRP\n"); -return -1; - if (!strcmp(howarg, "wipe")) { - how = CRYPTO_ENABLE_WIPE; - } else if (! strcmp(howarg, "inplace")) { - how = CRYPTO_ENABLE_INPLACE; - } else { - /* Shouldn't happen, as CommandListener vets the args */ - goto error_unencrypted; - } - - /* See if an encryption was underway and interrupted */ - if (how == CRYPTO_ENABLE_INPLACE - && get_crypt_ftr_and_key(&crypt_ftr) == 0 - && (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS)) { - previously_encrypted_upto = crypt_ftr.encrypted_upto; - crypt_ftr.encrypted_upto = 0; - crypt_ftr.flags &= ~CRYPT_ENCRYPTION_IN_PROGRESS; - - /* At this point, we are in an inconsistent state. Until we successfully - complete encryption, a reboot will leave us broken. So mark the - encryption failed in case that happens. - On successfully completing encryption, remove this flag */ - crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE; - - put_crypt_ftr_and_key(&crypt_ftr); - } - - property_get("ro.crypto.state", encrypted_state, ""); - if (!strcmp(encrypted_state, "encrypted") && !previously_encrypted_upto) { - printf("Device is already running encrypted, aborting"); - goto error_unencrypted; - } - - // TODO refactor fs_mgr_get_crypt_info to get both in one call - fs_mgr_get_crypt_info(fstab, key_loc, 0, sizeof(key_loc)); - fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev)); - - /* Get the size of the real block device */ - fd = open(real_blkdev, O_RDONLY); - if ( (nr_sec = get_blkdev_size(fd)) == 0) { - printf("Cannot get size of block device %s\n", real_blkdev); - goto error_unencrypted; - } - close(fd); - - /* If doing inplace encryption, make sure the orig fs doesn't include the crypto footer */ - if ((how == CRYPTO_ENABLE_INPLACE) && (!strcmp(key_loc, KEY_IN_FOOTER))) { - unsigned int fs_size_sec, max_fs_size_sec; - fs_size_sec = get_fs_size(real_blkdev); - if (fs_size_sec == 0) - fs_size_sec = get_f2fs_filesystem_size_sec(real_blkdev); - - max_fs_size_sec = nr_sec - (CRYPT_FOOTER_OFFSET / CRYPT_SECTOR_SIZE); - - if (fs_size_sec > max_fs_size_sec) { - printf("Orig filesystem overlaps crypto footer region. Cannot encrypt in place."); - goto error_unencrypted; - } - } - - /* Get a wakelock as this may take a while, and we don't want the - * device to sleep on us. We'll grab a partial wakelock, and if the UI - * wants to keep the screen on, it can grab a full wakelock. - */ - snprintf(lockid, sizeof(lockid), "enablecrypto%d", (int) getpid()); - acquire_wake_lock(PARTIAL_WAKE_LOCK, lockid); - - /* Get the sdcard mount point */ - sd_mnt_point = getenv("EMULATED_STORAGE_SOURCE"); - if (!sd_mnt_point) { - sd_mnt_point = getenv("EXTERNAL_STORAGE"); - } - if (!sd_mnt_point) { - sd_mnt_point = "/mnt/sdcard"; - } - - /* TODO - * Currently do not have test devices with multiple encryptable volumes. - * When we acquire some, re-add support. - */ - num_vols=0/*vold_getNumDirectVolumes()*/; - vol_list = malloc(sizeof(struct volume_info) * num_vols); - //vold_getDirectVolumeList(vol_list); - - for (i=0; i<num_vols; i++) { - if (should_encrypt(&vol_list[i])) { - printf("Cannot encrypt if there are multiple encryptable volumes" - "%s\n", vol_list[i].label); - goto error_unencrypted; - } - } - - /* The init files are setup to stop the class main and late start when - * vold sets trigger_shutdown_framework. - */ - property_set("vold.decrypt", "trigger_shutdown_framework"); - printf("Just asked init to shut down class main\n"); - - if (1 /*vold_unmountAllAsecs()*/) { - /* Just report the error. If any are left mounted, - * umounting /data below will fail and handle the error. - */ - printf("Error unmounting internal asecs"); - } - - property_get("ro.crypto.fuse_sdcard", fuse_sdcard, ""); - if (!strcmp(fuse_sdcard, "true")) { - /* This is a device using the fuse layer to emulate the sdcard semantics - * on top of the userdata partition. vold does not manage it, it is managed - * by the sdcard service. The sdcard service was killed by the property trigger - * above, so just unmount it now. We must do this _AFTER_ killing the framework, - * unlike the case for vold managed devices above. - */ - if (wait_and_unmount(sd_mnt_point, false)) { - goto error_shutting_down; - } - } - - /* Now unmount the /data partition. */ - if (wait_and_unmount(DATA_MNT_POINT, false)) { - if (allow_reboot) { - goto error_shutting_down; - } else { - goto error_unencrypted; - } - } - - /* Do extra work for a better UX when doing the long inplace encryption */ - if (how == CRYPTO_ENABLE_INPLACE) { - /* Now that /data is unmounted, we need to mount a tmpfs - * /data, set a property saying we're doing inplace encryption, - * and restart the framework. - */ - if (fs_mgr_do_tmpfs_mount(DATA_MNT_POINT)) { - goto error_shutting_down; - } - /* Tells the framework that inplace encryption is starting */ - property_set("vold.encrypt_progress", "0"); - - /* restart the framework. */ - /* Create necessary paths on /data */ - if (prep_data_fs()) { - goto error_shutting_down; - } - - /* Ugh, shutting down the framework is not synchronous, so until it - * can be fixed, this horrible hack will wait a moment for it all to - * shut down before proceeding. Without it, some devices cannot - * restart the graphics services. - */ - sleep(2); - - /* startup service classes main and late_start */ - property_set("vold.decrypt", "trigger_restart_min_framework"); - printf("Just triggered restart_min_framework\n"); - - /* OK, the framework is restarted and will soon be showing a - * progress bar. Time to setup an encrypted mapping, and - * either write a new filesystem, or encrypt in place updating - * the progress bar as we work. - */ - } - - /* Start the actual work of making an encrypted filesystem */ - /* Initialize a crypt_mnt_ftr for the partition */ - if (previously_encrypted_upto == 0) { - if (cryptfs_init_crypt_mnt_ftr(&crypt_ftr)) { - goto error_shutting_down; - } - - if (!strcmp(key_loc, KEY_IN_FOOTER)) { - crypt_ftr.fs_size = nr_sec - - (CRYPT_FOOTER_OFFSET / CRYPT_SECTOR_SIZE); - } else { - crypt_ftr.fs_size = nr_sec; - } - /* At this point, we are in an inconsistent state. Until we successfully - complete encryption, a reboot will leave us broken. So mark the - encryption failed in case that happens. - On successfully completing encryption, remove this flag */ - crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE; - crypt_ftr.crypt_type = crypt_type; - 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, &crypt_ftr)) { - printf("Cannot create encrypted master key\n"); - goto error_shutting_down; - } - - /* Write the key to the end of the partition */ - put_crypt_ftr_and_key(&crypt_ftr); - - /* If any persistent data has been remembered, save it. - * If none, create a valid empty table and save that. - */ - if (!persist_data) { - pdata = malloc(CRYPT_PERSIST_DATA_SIZE); - if (pdata) { - init_empty_persist_data(pdata, CRYPT_PERSIST_DATA_SIZE); - persist_data = pdata; - } - } - if (persist_data) { - save_persistent_data(); - } - } - - decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0); - create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev, - "userdata"); - - /* If we are continuing, check checksums match */ - rc = 0; - if (previously_encrypted_upto) { - __le8 hash_first_block[SHA256_DIGEST_LENGTH]; - rc = cryptfs_SHA256_fileblock(crypto_blkdev, hash_first_block); - - if (!rc && memcmp(hash_first_block, crypt_ftr.hash_first_block, - sizeof(hash_first_block)) != 0) { - printf("Checksums do not match - trigger wipe"); - rc = -1; - } - } - - if (!rc) { - rc = cryptfs_enable_all_volumes(&crypt_ftr, how, - crypto_blkdev, real_blkdev, - previously_encrypted_upto); - } - - /* Calculate checksum if we are not finished */ - if (!rc && crypt_ftr.encrypted_upto != crypt_ftr.fs_size) { - rc = cryptfs_SHA256_fileblock(crypto_blkdev, - crypt_ftr.hash_first_block); - if (rc) { - printf("Error calculating checksum for continuing encryption"); - rc = -1; - } - } - - /* Undo the dm-crypt mapping whether we succeed or not */ - delete_crypto_blk_dev("userdata"); - - free(vol_list); - - if (! rc) { - /* Success */ - crypt_ftr.flags &= ~CRYPT_INCONSISTENT_STATE; - - if (crypt_ftr.encrypted_upto != crypt_ftr.fs_size) { - printf("Encrypted up to sector %lld - will continue after reboot", - crypt_ftr.encrypted_upto); - crypt_ftr.flags |= CRYPT_ENCRYPTION_IN_PROGRESS; - } - - put_crypt_ftr_and_key(&crypt_ftr); - - if (crypt_ftr.encrypted_upto == crypt_ftr.fs_size) { - char value[PROPERTY_VALUE_MAX]; - property_get("ro.crypto.state", value, ""); - if (!strcmp(value, "")) { - /* default encryption - continue first boot sequence */ - property_set("ro.crypto.state", "encrypted"); - release_wake_lock(lockid); - cryptfs_check_passwd(DEFAULT_PASSWORD); - cryptfs_restart_internal(1); - return 0; - } else { - sleep(2); /* Give the UI a chance to show 100% progress */ - cryptfs_reboot(reboot); - } - } else { - sleep(2); /* Partially encrypted, ensure writes flushed to ssd */ - cryptfs_reboot(shutdown); - } - } else { - char value[PROPERTY_VALUE_MAX]; - - property_get("ro.vold.wipe_on_crypt_fail", value, "0"); - if (!strcmp(value, "1")) { - /* wipe data if encryption failed */ - printf("encryption failed - rebooting into recovery to wipe data\n"); - mkdir("/cache/recovery", 0700); - int fd = open("/cache/recovery/command", O_RDWR|O_CREAT|O_TRUNC, 0600); - if (fd >= 0) { - write(fd, "--wipe_data\n", strlen("--wipe_data\n") + 1); - write(fd, "--reason=cryptfs_enable_internal\n", strlen("--reason=cryptfs_enable_internal\n") + 1); - close(fd); - } else { - printf("could not open /cache/recovery/command\n"); - } - cryptfs_reboot(recovery); - } else { - /* set property to trigger dialog */ - property_set("vold.encrypt_progress", "error_partially_encrypted"); - release_wake_lock(lockid); - } - return -1; - } - - /* hrm, the encrypt step claims success, but the reboot failed. - * This should not happen. - * Set the property and return. Hope the framework can deal with it. - */ - property_set("vold.encrypt_progress", "error_reboot_failed"); - release_wake_lock(lockid); - return rc; - -error_unencrypted: - free(vol_list); - property_set("vold.encrypt_progress", "error_not_encrypted"); - if (lockid[0]) { - release_wake_lock(lockid); - } - return -1; - -error_shutting_down: - /* we failed, and have not encrypted anthing, so the users's data is still intact, - * but the framework is stopped and not restarted to show the error, so it's up to - * vold to restart the system. - */ - printf("Error enabling encryption after framework is shutdown, no data changed, restarting system"); - cryptfs_reboot(reboot); - - /* shouldn't get here */ - property_set("vold.encrypt_progress", "error_shutting_down"); - free(vol_list); - if (lockid[0]) { - release_wake_lock(lockid); - } - return -1; -} - -int cryptfs_enable(char *howarg, int type, char *passwd, int allow_reboot) -{ - char* adjusted_passwd = adjust_passwd(passwd); - if (adjusted_passwd) { - passwd = adjusted_passwd; - } - - int rc = cryptfs_enable_internal(howarg, type, passwd, allow_reboot); - - free(adjusted_passwd); - return rc; -} - -int cryptfs_enable_default(char *howarg, int allow_reboot) -{ - return cryptfs_enable_internal(howarg, CRYPT_TYPE_DEFAULT, - DEFAULT_PASSWORD, allow_reboot); -} - -int cryptfs_changepw(int crypt_type, const char *newpw) -{ - struct crypt_mnt_ftr crypt_ftr; - unsigned char decrypted_master_key[KEY_LEN_BYTES]; - - /* This is only allowed after we've successfully decrypted the master key */ - if (!master_key_saved) { - printf("Key not saved, aborting"); - return -1; - } - - if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) { - printf("Invalid crypt_type %d", crypt_type); - return -1; - } - - /* get key */ - if (get_crypt_ftr_and_key(&crypt_ftr)) { - printf("Error getting crypt footer and key"); - return -1; - } - - crypt_ftr.crypt_type = crypt_type; - - char* adjusted_passwd = adjust_passwd(newpw); - if (adjusted_passwd) { - newpw = adjusted_passwd; - } - - encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD - : newpw, - crypt_ftr.salt, - saved_master_key, - crypt_ftr.master_key, - &crypt_ftr); - - /* save the key */ - put_crypt_ftr_and_key(&crypt_ftr); - - free(adjusted_passwd); - return 0; -} - -static int persist_get_key(char *fieldname, char *value) -{ - unsigned int i; - - if (persist_data == NULL) { - return -1; - } - for (i = 0; i < persist_data->persist_valid_entries; i++) { - if (!strncmp(persist_data->persist_entry[i].key, fieldname, PROPERTY_KEY_MAX)) { - /* We found it! */ - strlcpy(value, persist_data->persist_entry[i].val, PROPERTY_VALUE_MAX); - return 0; - } - } - - return -1; -} - -static int persist_set_key(char *fieldname, char *value, int encrypted) -{ - unsigned int i; - unsigned int num; - struct crypt_mnt_ftr crypt_ftr; - unsigned int max_persistent_entries; - unsigned int dsize; - - if (persist_data == NULL) { - return -1; - } - - /* If encrypted, use the values from the crypt_ftr, otherwise - * use the values for the current spec. - */ - if (encrypted) { - if(get_crypt_ftr_and_key(&crypt_ftr)) { - return -1; - } - dsize = crypt_ftr.persist_data_size; - } else { - dsize = CRYPT_PERSIST_DATA_SIZE; - } - max_persistent_entries = (dsize - sizeof(struct crypt_persist_data)) / - sizeof(struct crypt_persist_entry); - - num = persist_data->persist_valid_entries; - - for (i = 0; i < num; i++) { - if (!strncmp(persist_data->persist_entry[i].key, fieldname, PROPERTY_KEY_MAX)) { - /* We found an existing entry, update it! */ - memset(persist_data->persist_entry[i].val, 0, PROPERTY_VALUE_MAX); - strlcpy(persist_data->persist_entry[i].val, value, PROPERTY_VALUE_MAX); - return 0; - } - } - - /* We didn't find it, add it to the end, if there is room */ - if (persist_data->persist_valid_entries < max_persistent_entries) { - memset(&persist_data->persist_entry[num], 0, sizeof(struct crypt_persist_entry)); - strlcpy(persist_data->persist_entry[num].key, fieldname, PROPERTY_KEY_MAX); - strlcpy(persist_data->persist_entry[num].val, value, PROPERTY_VALUE_MAX); - persist_data->persist_valid_entries++; - return 0; - } - - return -1; -} - -/* Return the value of the specified field. */ -int cryptfs_getfield(char *fieldname, char *value, int len) -{ - char temp_value[PROPERTY_VALUE_MAX]; - char real_blkdev[MAXPATHLEN]; - /* 0 is success, 1 is not encrypted, - * -1 is value not set, -2 is any other error - */ - int rc = -2; - - if (persist_data == NULL) { - load_persistent_data(); - if (persist_data == NULL) { - printf("Getfield error, cannot load persistent data"); - goto out; - } - } - - if (!persist_get_key(fieldname, temp_value)) { - /* We found it, copy it to the caller's buffer and return */ - strlcpy(value, temp_value, len); - rc = 0; - } else { - /* Sadness, it's not there. Return the error */ - rc = -1; - } - -out: - return rc; -} - -/* Set the value of the specified field. */ -int cryptfs_setfield(char *fieldname, char *value) -{ - struct crypt_persist_data stored_pdata; - struct crypt_persist_data *pdata_p; - struct crypt_mnt_ftr crypt_ftr; - char encrypted_state[PROPERTY_VALUE_MAX]; - /* 0 is success, -1 is an error */ - int rc = -1; - int encrypted = 0; - - if (persist_data == NULL) { - load_persistent_data(); - if (persist_data == NULL) { - printf("Setfield error, cannot load persistent data"); - goto out; - } - } - - property_get("ro.crypto.state", encrypted_state, ""); - if (!strcmp(encrypted_state, "encrypted") ) { - encrypted = 1; - } - - if (persist_set_key(fieldname, value, encrypted)) { - goto out; - } - - /* If we are running encrypted, save the persistent data now */ - if (encrypted) { - if (save_persistent_data()) { - printf("Setfield error, cannot save persistent data"); - goto out; - } - } - - rc = 0; - -out: - return rc; -} - -/* Checks userdata. Attempt to mount the volume if default- - * encrypted. - * On success trigger next init phase and return 0. - * Currently do not handle failure - see TODO below. - */ -int cryptfs_mount_default_encrypted(void) -{ - char decrypt_state[PROPERTY_VALUE_MAX]; - property_get("vold.decrypt", decrypt_state, "0"); - if (!strcmp(decrypt_state, "0")) { - printf("Not encrypted - should not call here"); - } else { - int crypt_type = cryptfs_get_password_type(); - if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) { - printf("Bad crypt type - error"); - } else if (crypt_type != CRYPT_TYPE_DEFAULT) { - printf("Password is not default - " - "starting min framework to prompt"); - property_set("vold.decrypt", "trigger_restart_min_framework"); - return 0; - } else if (cryptfs_check_passwd(DEFAULT_PASSWORD) == 0) { - printf("Password is default - restarting filesystem"); - cryptfs_restart_internal(0); - return 0; - } else { - printf("Encrypted, default crypt type but can't decrypt"); - } - } - - /** Corrupt. Allow us to boot into framework, which will detect bad - crypto when it calls do_crypto_complete, then do a factory reset - */ - property_set("vold.decrypt", "trigger_restart_min_framework"); - return 0; -} - /* Returns type of the password, default, pattern, pin or password. */ int cryptfs_get_password_type(void) { struct crypt_mnt_ftr crypt_ftr; - char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; - char propbuf[PROPERTY_VALUE_MAX]; - - property_get("ro.hardware", propbuf, ""); - snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); - - fstab = fs_mgr_read_fstab(fstab_filename); - if (!fstab) { - printf("failed to open %s\n", fstab_filename); - return -1; - } if (get_crypt_ftr_and_key(&crypt_ftr)) { printf("Error getting crypt footer and key\n"); @@ -3595,26 +1445,3 @@ int cryptfs_get_password_type(void) return crypt_ftr.crypt_type; } - -char* cryptfs_get_password() -{ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - if (now.tv_sec < password_expiry_time) { - return password; - } else { - cryptfs_clear_password(); - return 0; - } -} - -void cryptfs_clear_password() -{ - if (password) { - size_t len = strlen(password); - memset(password, 0, len); - free(password); - password = 0; - password_expiry_time = 0; - } -} diff --git a/crypto/lollipop/cryptfs.h b/crypto/lollipop/cryptfs.h index b95a290cf..8cb8a7a32 100644 --- a/crypto/lollipop/cryptfs.h +++ b/crypto/lollipop/cryptfs.h @@ -208,24 +208,11 @@ extern "C" { typedef int (*kdf_func)(const char *passwd, const unsigned char *salt, unsigned char *ikey, void *params); - int cryptfs_crypto_complete(void); - int cryptfs_check_footer(void); + void set_partition_data(const char* block_device, const char* key_location, const char* fs); + int cryptfs_check_footer(); int cryptfs_check_passwd(char *pw); int cryptfs_verify_passwd(char *newpw); - int cryptfs_restart(void); - int cryptfs_enable(char *flag, int type, char *passwd, int allow_reboot); - int cryptfs_changepw(int type, const char *newpw); - int cryptfs_enable_default(char *flag, int allow_reboot); - 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_getfield(char *fieldname, char *value, int len); - int cryptfs_setfield(char *fieldname, char *value); - int cryptfs_mount_default_encrypted(void); int cryptfs_get_password_type(void); - char* cryptfs_get_password(void); - void cryptfs_clear_password(void); #ifdef __cplusplus } #endif diff --git a/crypto/scrypt/Android.mk b/crypto/scrypt/Android.mk index a427de655..4514f9467 100644 --- a/crypto/scrypt/Android.mk +++ b/crypto/scrypt/Android.mk @@ -1,5 +1,4 @@ LOCAL_PATH := $(call my-dir) -#include $(call all-named-subdir-makefiles,tests) # Enable to be able to use ALOG* with #include "cutils/log.h" #log_c_includes += system/core/include @@ -10,3 +9,5 @@ LOCAL_PATH := $(call my-dir) # that import_openssl.sh import won't remove them. include $(LOCAL_PATH)/build-config.mk include $(LOCAL_PATH)/Scrypt.mk + +include $(LOCAL_PATH)/tests/Android.mk diff --git a/crypto/scrypt/Scrypt-config.mk b/crypto/scrypt/Scrypt-config.mk index c0b00d873..bbe10631e 100644 --- a/crypto/scrypt/Scrypt-config.mk +++ b/crypto/scrypt/Scrypt-config.mk @@ -77,7 +77,7 @@ target_arch := unknown_arch endif target_c_flags := $(common_c_flags) $($(target_arch)_c_flags) $(local_c_flags) -target_c_includes := $(addprefix $(commands_recovery_local_path)/crypto/scrypt/,$(common_c_includes)) $(local_c_includes) +target_c_includes := $(addprefix external/scrypt/,$(common_c_includes)) $(local_c_includes) target_src_files := $(common_src_files) $($(target_arch)_src_files) target_src_files := $(filter-out $($(target_arch)_exclude_files), $(target_src_files)) @@ -97,7 +97,7 @@ host_arch := unknown_arch endif host_c_flags := $(common_c_flags) $($(host_arch)_c_flags) $(local_c_flags) -host_c_includes := $(addprefix $(commands_recovery_local_path)/crypto/scrypt/,$(common_c_includes)) $(local_c_includes) +host_c_includes := $(addprefix external/scrypt/,$(common_c_includes)) $(local_c_includes) host_src_files := $(common_src_files) $($(host_arch)_src_files) host_src_files := $(filter-out $($(host_arch)_exclude_files), $(host_src_files)) diff --git a/crypto/scrypt/tests/Android.mk b/crypto/scrypt/tests/Android.mk index 60257e0f9..07c21023d 100644 --- a/crypto/scrypt/tests/Android.mk +++ b/crypto/scrypt/tests/Android.mk @@ -3,6 +3,8 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk + LOCAL_SRC_FILES:= \ scrypt_test.cpp @@ -18,6 +20,6 @@ LOCAL_STATIC_LIBRARIES := \ libgtest \ libgtest_main -LOCAL_MODULE := scrypt_test_twrp +LOCAL_MODULE := scrypttwrp_test include $(BUILD_NATIVE_TEST) diff --git a/crypto/scrypt/tests/scrypt_test.cpp b/crypto/scrypt/tests/scrypt_test.cpp index 28334d6f5..ffb568df9 100644 --- a/crypto/scrypt/tests/scrypt_test.cpp +++ b/crypto/scrypt/tests/scrypt_test.cpp @@ -15,8 +15,8 @@ */ #define LOG_TAG "scrypt_test" +#include <UniquePtr.h> #include <utils/Log.h> -#include <utils/UniquePtr.h> #include <gtest/gtest.h> |