fscrypt: move fscrypt to android_system_vold
Change-Id: I2cb7385541b8d9c7f1d8de0cef8ed3803b457b8c
diff --git a/Android.mk b/Android.mk
index c2f1f59..61cec06 100755
--- a/Android.mk
+++ b/Android.mk
@@ -90,6 +90,7 @@
system/gsid/include/ \
system/core/init/ \
system/extras/ext4_utils/include \
+ system/vold
ifneq ($(TARGET_RECOVERY_REBOOT_SRC),)
LOCAL_SRC_FILES += $(TARGET_RECOVERY_REBOOT_SRC)
@@ -108,6 +109,7 @@
system/extras \
packages/modules/adb \
system/core/libsparse \
+ system/vold \
external/zlib \
system/libziparchive/include \
external/freetype/include \
@@ -127,7 +129,7 @@
$(LOCAL_PATH)/minuitwrp/include \
$(LOCAL_PATH)/twinstall/include
-LOCAL_STATIC_LIBRARIES += libguitwrp
+LOCAL_STATIC_LIBRARIES += libguitwrp libvold
LOCAL_SHARED_LIBRARIES += libz libc libcutils libstdc++ libtar libblkid libminuitwrp libmtdutils libtwadbbu
LOCAL_SHARED_LIBRARIES += libbootloader_message libcrecovery libtwrpdigest libc++ libaosprecovery libcrypto libbase
LOCAL_SHARED_LIBRARIES += libziparchive libselinux libdl_android.bootstrap
@@ -296,12 +298,6 @@
ifeq ($(TW_NO_HAPTICS), true)
LOCAL_CFLAGS += -DTW_NO_HAPTICS
endif
-ifeq ($(TW_INCLUDE_JB_CRYPTO), true)
- TW_INCLUDE_CRYPTO := true
-endif
-ifeq ($(TW_INCLUDE_L_CRYPTO), true)
- TW_INCLUDE_CRYPTO := true
-endif
ifneq ($(TW_ADDITIONAL_APEX_FILES),)
LOCAL_CFLAGS += -DTW_ADDITIONAL_APEX_FILES=$(TW_ADDITIONAL_APEX_FILES)
endif
@@ -313,14 +309,27 @@
endif
ifeq ($(TW_INCLUDE_CRYPTO), true)
LOCAL_CFLAGS += -DTW_INCLUDE_CRYPTO -DUSE_FSCRYPT -Wno-macro-redefined
- LOCAL_SHARED_LIBRARIES += libcryptfsfde
- LOCAL_SHARED_LIBRARIES += libgpt_twrp libstatssocket.recovery
+ LOCAL_SHARED_LIBRARIES += libgpt_twrp
LOCAL_C_INCLUDES += external/boringssl/src/include bootable/recovery/crypto
- LOCAL_C_INCLUDES += $(commands_TWRP_local_path)/crypto/fscrypt
TW_INCLUDE_CRYPTO_FBE := true
LOCAL_CFLAGS += -DTW_INCLUDE_FBE
- LOCAL_SHARED_LIBRARIES += libtwrpfscrypt android.frameworks.stats@1.0 android.hardware.authsecret@1.0 \
- android.hardware.oemlock@1.0
+ LOCAL_SHARED_LIBRARIES += android.frameworks.stats@1.0 android.hardware.authsecret@1.0 \
+ android.security.authorization-ndk_platform \
+ android.hardware.oemlock@1.0 libf2fs_sparseblock libbinder libbinder_ndk \
+ libandroidicu.recovery \
+ android.hardware.gatekeeper@1.0 \
+ android.hardware.weaver@1.0 \
+ android.frameworks.stats@1.0 \
+ android.security.maintenance-ndk_platform \
+ android.system.keystore2-V1-ndk_platform \
+ libkeyutils \
+ liblog \
+ libsqlite.recovery \
+ libkeystoreinfo.recovery \
+ libgatekeeper_aidl
+
+ LOCAL_STATIC_LIBRARIES += libkeymint_support
+
LOCAL_CFLAGS += -DTW_INCLUDE_FBE_METADATA_DECRYPT
ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),)
ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),false)
@@ -507,7 +516,13 @@
TWRP_REQUIRED_MODULES += \
vold_prepare_subdirs \
task_recovery_profiles.json \
- fscryptpolicyget
+ fscryptpolicyget.recovery \
+ keystore_auth \
+ keystore2 \
+ android.system.keystore2-service.xml \
+ keystore2.rc \
+ plat_keystore2_key_contexts
+
ifneq ($(TW_INCLUDE_CRYPTO_FBE),)
TWRP_REQUIRED_MODULES += \
plat_service_contexts \
@@ -707,11 +722,8 @@
endif
ifeq ($(TW_INCLUDE_CRYPTO), true)
- include $(commands_TWRP_local_path)/crypto/fde/Android.mk
+ # include $(commands_TWRP_local_path)/crypto/fde/Android.mk
include $(commands_TWRP_local_path)/crypto/scrypt/Android.mk
- ifeq ($(TW_INCLUDE_CRYPTO_FBE), true)
- include $(commands_TWRP_local_path)/crypto/fscrypt/Android.mk
- endif
ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),)
ifneq ($(TW_CRYPTO_USE_SYSTEM_VOLD),false)
include $(commands_TWRP_local_path)/crypto/vold_decrypt/Android.mk
diff --git a/crypto/fde/Android.mk b/crypto/fde/Android.mk
deleted file mode 100755
index faf7da8..0000000
--- a/crypto/fde/Android.mk
+++ /dev/null
@@ -1,126 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-ifeq ($(TW_INCLUDE_CRYPTO), true)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libcryptfsfde
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := cryptfs.cpp
-LOCAL_SHARED_LIBRARIES := libcrypto libhardware libcutils libstdc++
-LOCAL_STATIC_LIBRARIES := libscrypttwrp_static
-LOCAL_C_INCLUDES := external/openssl/include $(commands_recovery_local_path)/crypto/scrypt/lib/crypto
-ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0)
- LOCAL_C_INCLUDES += bionic external/stlport/stlport
- LOCAL_SHARED_LIBRARIES += libstlport
- LOCAL_CPPFLAGS := -std=c++11
-endif
-
-LOCAL_C_INCLUDES += $(commands_TWRP_local_path)/crypto/fscrypt
-
-ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26; echo $$?),0)
- #8.0 or higher
- LOCAL_C_INCLUDES += external/boringssl/src/include
- ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 29; echo $$?),0)
- LOCAL_SHARED_LIBRARIES += libtwrpfscrypt
- else
- LOCAL_SHARED_LIBRARIES += libe4crypt
- endif
- LOCAL_SHARED_LIBRARIES += libselinux libc libc++ libbase libcrypto libcutils libkeymaster_messages libhardware libprotobuf-cpp-lite \
- android.hardware.keymaster@3.0 libkeystore_binder libhidlbase libutils libbinder
- ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0)
- #9.0 rules
- LOCAL_CFLAGS += -Wno-unused-variable -Wno-sign-compare -Wno-unused-parameter -Wno-comment
- LOCAL_SHARED_LIBRARIES += android.hardware.keymaster@4.0 libkeymaster4support libkeyutils
- LOCAL_CFLAGS += -DTW_KEYMASTER_MAX_API=4
- else
- #8.x rules
- ifneq ($(wildcard system/core/libkeyutils/Android.bp),)
- #only present in some 8.0 trees and should be in all 8.1 trees
- LOCAL_SHARED_LIBRARIES += libkeyutils
- endif
- LOCAL_SHARED_LIBRARIES += libsoftkeymaster
- LOCAL_CFLAGS += -DTW_KEYMASTER_MAX_API=3
- endif
-else
- # <= 7.x rules
- ifneq ($(wildcard hardware/libhardware/include/hardware/keymaster0.h),)
- LOCAL_C_INCLUDES += external/boringssl/src/include
- LOCAL_CFLAGS += -DTW_KEYMASTER_MAX_API=1
- else
- LOCAL_CFLAGS += -DTW_KEYMASTER_MAX_API=0
- endif
-endif
-ifeq ($(TARGET_HW_DISK_ENCRYPTION),true)
- ifeq ($(TARGET_CRYPTFS_HW_PATH),)
- LOCAL_C_INCLUDES += device/qcom/common/cryptfs_hw
- else
- LOCAL_C_INCLUDES += $(TARGET_CRYPTFS_HW_PATH)
- endif
- LOCAL_SHARED_LIBRARIES += libcryptfs_hw
- LOCAL_CFLAGS += -DCONFIG_HW_DISK_ENCRYPTION
-endif
-
-include $(BUILD_SHARED_LIBRARY)
-
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := twrpdec
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/
-LOCAL_SRC_FILES := main.cpp cryptfs.cpp
-LOCAL_SHARED_LIBRARIES := libcrypto libhardware libcutils libc libstdc++
-LOCAL_C_INCLUDES := external/openssl/include $(commands_recovery_local_path)/crypto/scrypt/lib/crypto
-ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 23; echo $$?),0)
- LOCAL_C_INCLUDES += bionic external/stlport/stlport
- LOCAL_SHARED_LIBRARIES += libstlport
- LOCAL_CPPFLAGS := -std=c++11
-endif
-
-ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26; echo $$?),0)
- #8.0 or higher
- LOCAL_C_INCLUDES += external/boringssl/src/include
- ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 29; echo $$?),0)
- LOCAL_SHARED_LIBRARIES += libtwrpfscrypt
- else
- LOCAL_SHARED_LIBRARIES += libe4crypt
- endif
- LOCAL_SHARED_LIBRARIES += libselinux libc libc++ libbase libcrypto libcutils libkeymaster_messages libhardware libprotobuf-cpp-lite \
- android.hardware.keymaster@3.0 libkeystore_binder libhidlbase libutils libbinder
- ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 28; echo $$?),0)
- #9.0 rules
- LOCAL_CFLAGS += -Wno-unused-variable -Wno-sign-compare -Wno-unused-parameter -Wno-comment
- LOCAL_SHARED_LIBRARIES += android.hardware.keymaster@4.0 libkeymaster4support libkeyutils
- LOCAL_CFLAGS += -DTW_KEYMASTER_MAX_API=4
- else
- #8.x rules
- ifneq ($(wildcard system/core/libkeyutils/Android.bp),)
- #only present in some 8.0 trees and should be in all 8.1 trees
- LOCAL_SHARED_LIBRARIES += libkeyutils
- endif
- LOCAL_SHARED_LIBRARIES += libsoftkeymaster
- LOCAL_CFLAGS += -DTW_KEYMASTER_MAX_API=3
- endif
-else
- # <= 7.x rules
- ifneq ($(wildcard hardware/libhardware/include/hardware/keymaster0.h),)
- LOCAL_C_INCLUDES += external/boringssl/src/include
- LOCAL_CFLAGS += -DTW_KEYMASTER_MAX_API=1
- else
- LOCAL_CFLAGS += -DTW_KEYMASTER_MAX_API=0
- endif
-endif
-ifeq ($(TARGET_HW_DISK_ENCRYPTION),true)
- ifeq ($(TARGET_CRYPTFS_HW_PATH),)
- LOCAL_C_INCLUDES += device/qcom/common/cryptfs_hw
- else
- LOCAL_C_INCLUDES += $(TARGET_CRYPTFS_HW_PATH)
- endif
- LOCAL_SHARED_LIBRARIES += libcryptfs_hw
- LOCAL_CFLAGS += -DCONFIG_HW_DISK_ENCRYPTION
-endif
-
-LOCAL_WHOLE_STATIC_LIBRARIES += libscrypttwrp_static
-include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/crypto/fde/cryptfs.cpp b/crypto/fde/cryptfs.cpp
deleted file mode 100644
index fa0dc78..0000000
--- a/crypto/fde/cryptfs.cpp
+++ /dev/null
@@ -1,1848 +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 <ctype.h>
-#include <fcntl.h>
-#include <inttypes.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_utils/ext4_crypt.h>
-//#include <ext4_utils/ext4_utils.h>
-#include <linux/kdev_t.h>
-//#include <fs_mgr.h>
-#include <time.h>
-#include <math.h>
-//#include <selinux/selinux.h>
-#include "cryptfs.h"
-//#include "secontext.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 "ScryptParameters.h"
-//#include "VolumeManager.h"
-//#include "VoldUtil.h"
-//#include "Ext4Crypt.h"
-//#include "f2fs_sparseblock.h"
-//#include "EncryptInplace.h"
-//#include "Process.h"
-#include "Keymaster.h"
-#if TW_KEYMASTER_MAX_API == 0
-#include <hardware/keymaster.h>
-#else // so far, all trees that have keymaster >= 1 have keymaster 1 support
-#include <stdbool.h>
-#include <openssl/evp.h>
-#include <openssl/sha.h>
-#include <hardware/keymaster0.h>
-#include <hardware/keymaster1.h>
-#include <hardware/keymaster2.h>
-#endif
-//#include "android-base/properties.h"
-//#include <bootloader_message/bootloader_message.h>
-#ifdef CONFIG_HW_DISK_ENCRYPTION
-#include <cryptfs_hw.h>
-#endif
-extern "C" {
-#include <crypto_scrypt.h>
-}
-#include <string>
-#include <vector>
-
-#define ALOGE(...) fprintf(stdout, "E:" __VA_ARGS__)
-#define SLOGE(...) fprintf(stdout, "E:" __VA_ARGS__)
-#define SLOGW(...) fprintf(stdout, "W:" __VA_ARGS__)
-#define SLOGI(...) fprintf(stdout, "I:" __VA_ARGS__)
-#define SLOGD(...) fprintf(stdout, "D:" __VA_ARGS__)
-
-#define UNUSED __attribute__((unused))
-
-#define DM_CRYPT_BUF_SIZE 4096
-
-#define HASH_COUNT 2000
-
-#ifndef min /* already defined by windows.h */
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
-constexpr size_t INTERMEDIATE_KEY_LEN_BYTES = 16;
-constexpr size_t INTERMEDIATE_IV_LEN_BYTES = 16;
-constexpr size_t INTERMEDIATE_BUF_SIZE =
- (INTERMEDIATE_KEY_LEN_BYTES + INTERMEDIATE_IV_LEN_BYTES);
-
-// SCRYPT_LEN is used by struct crypt_mnt_ftr for its intermediate key.
-static_assert(INTERMEDIATE_BUF_SIZE == SCRYPT_LEN,
- "Mismatch of intermediate key sizes");
-
-#define KEY_IN_FOOTER "footer"
-
-#define DEFAULT_HEX_PASSWORD "64656661756c745f70617373776f7264"
-#define DEFAULT_PASSWORD "default_password"
-
-#define CRYPTO_BLOCK_DEVICE "userdata"
-
-#define TABLE_LOAD_RETRIES 10
-
-#define RSA_KEY_SIZE 2048
-#define RSA_KEY_SIZE_BYTES (RSA_KEY_SIZE / 8)
-#define RSA_EXPONENT 0x10001
-#define KEYMASTER_CRYPTFS_RATE_LIMIT 1 // Maximum one try per second
-#define KEY_LEN_BYTES 16
-
-#define RETRY_MOUNT_ATTEMPTS 10
-#define RETRY_MOUNT_DELAY_SECONDS 1
-
-#define CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE (1)
-
-static unsigned char saved_master_key[MAX_KEY_LEN];
-static char *saved_mount_point;
-static int master_key_saved = 0;
-static struct crypt_persist_data *persist_data = NULL;
-
-static int previous_type;
-
-static char key_fname[PROPERTY_VALUE_MAX] = "";
-static char real_blkdev[PROPERTY_VALUE_MAX] = "";
-static char file_system[PROPERTY_VALUE_MAX] = "";
-
-static void get_blkdev_size(int fd, unsigned long *nr_sec)
-{
- if ( (ioctl(fd, BLKGETSIZE, nr_sec)) == -1) {
- *nr_sec = 0;
- }
-}
-
-#if TW_KEYMASTER_MAX_API == 0
-static int keymaster_init(keymaster_device_t **keymaster_dev)
-{
- int rc;
-
- const hw_module_t* mod;
- rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
- if (rc) {
- printf("could not find any keystore module\n");
- goto out;
- }
-
- rc = keymaster_open(mod, keymaster_dev);
- if (rc) {
- printf("could not open keymaster device in %s (%s)\n",
- KEYSTORE_HARDWARE_MODULE_ID, strerror(-rc));
- goto out;
- }
-
- return 0;
-
-out:
- *keymaster_dev = NULL;
- return rc;
-}
-#else //TW_KEYMASTER_MAX_API == 0
-static int keymaster_init(keymaster0_device_t **keymaster0_dev,
- keymaster1_device_t **keymaster1_dev,
- keymaster2_device_t **keymaster2_dev)
-{
- int rc;
-
- const hw_module_t* mod;
- rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
- if (rc) {
- printf("could not find any keystore module\n");
- goto err;
- }
-
- printf("keymaster module name is %s\n", mod->name);
- printf("keymaster version is %d\n", mod->module_api_version);
-
- *keymaster0_dev = NULL;
- *keymaster1_dev = NULL;
- *keymaster2_dev = NULL;
- if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_2_0) {
- printf("Found keymaster2 module, using keymaster2 API.\n");
- rc = keymaster2_open(mod, keymaster2_dev);
- } else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
- printf("Found keymaster1 module, using keymaster1 API.\n");
- rc = keymaster1_open(mod, keymaster1_dev);
- } else {
- printf("Found keymaster0 module, using keymaster0 API.\n");
- rc = keymaster0_open(mod, keymaster0_dev);
- }
-
- if (rc) {
- printf("could not open keymaster device in %s (%s)\n",
- KEYSTORE_HARDWARE_MODULE_ID, strerror(-rc));
- goto err;
- }
-
- return 0;
-
-err:
- *keymaster0_dev = NULL;
- *keymaster1_dev = NULL;
- *keymaster2_dev = NULL;
- return rc;
-}
-#endif //TW_KEYMASTER_MAX_API == 0
-
-#ifdef CONFIG_HW_DISK_ENCRYPTION
-static int scrypt_keymaster(const char *passwd, const unsigned char *salt,
- unsigned char *ikey, void *params);
-static void convert_key_to_hex_ascii(const unsigned char *master_key,
- unsigned int keysize, char *master_key_ascii);
-static int test_mount_hw_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
- const char *passwd, const char *mount_point, const char *label);
-int cryptfs_check_passwd_hw(char *passwd);
-int cryptfs_get_master_key(struct crypt_mnt_ftr* ftr, const char* password,
- unsigned char* master_key);
-
-static void convert_key_to_hex_ascii_for_upgrade(const 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 ? 0x57 : 0x30);
-
- nibble = master_key[i] & 0xf;
- master_key_ascii[a + 1] = nibble + (nibble > 9 ? 0x57 : 0x30);
- }
-
- /* Add the null termination */
- master_key_ascii[a] = '\0';
-}
-
-static int get_keymaster_hw_fde_passwd(const char* passwd, unsigned char* newpw,
- unsigned char* salt,
- const struct crypt_mnt_ftr *ftr)
-{
- /* if newpw updated, return 0
- * if newpw not updated return -1
- */
- int rc = -1;
-
- if (should_use_keymaster()) {
- if (scrypt_keymaster(passwd, salt, newpw, (void*)ftr)) {
- SLOGE("scrypt failed");
- } else {
- rc = 0;
- }
- }
-
- return rc;
-}
-
-static int verify_hw_fde_passwd(const char *passwd, struct crypt_mnt_ftr* crypt_ftr)
-{
- unsigned char newpw[32] = {0};
- int key_index;
- SLOGI("starting verify_hw_fde_passwd\n");
- if (get_keymaster_hw_fde_passwd(passwd, newpw, crypt_ftr->salt, crypt_ftr))
- key_index = set_hw_device_encryption_key(passwd,
- (char*) crypt_ftr->crypto_type_name);
- else
- key_index = set_hw_device_encryption_key((const char*)newpw,
- (char*) crypt_ftr->crypto_type_name);
- return key_index;
-}
-
-static int verify_and_update_hw_fde_passwd(const char *passwd,
- struct crypt_mnt_ftr* crypt_ftr)
-{
- char* new_passwd = NULL;
- unsigned char newpw[32] = {0};
- int key_index = -1;
- int passwd_updated = -1;
- int ascii_passwd_updated = (crypt_ftr->flags & CRYPT_ASCII_PASSWORD_UPDATED);
-
- key_index = verify_hw_fde_passwd(passwd, crypt_ftr);
- if (key_index < 0) {
- ++crypt_ftr->failed_decrypt_count;
-
- if (ascii_passwd_updated) {
- SLOGI("Ascii password was updated");
- } else {
- /* Code in else part would execute only once:
- * When device is upgraded from L->M release.
- * Once upgraded, code flow should never come here.
- * L release passed actual password in hex, so try with hex
- * Each nible of passwd was encoded as a byte, so allocate memory
- * twice of password len plus one more byte for null termination
- */
- if (crypt_ftr->crypt_type == CRYPT_TYPE_DEFAULT) {
- new_passwd = (char*)malloc(strlen(DEFAULT_HEX_PASSWORD) + 1);
- if (new_passwd == NULL) {
- SLOGE("System out of memory. Password verification incomplete");
- goto out;
- }
- strlcpy(new_passwd, DEFAULT_HEX_PASSWORD, strlen(DEFAULT_HEX_PASSWORD) + 1);
- } else {
- new_passwd = (char*)malloc(strlen(passwd) * 2 + 1);
- if (new_passwd == NULL) {
- SLOGE("System out of memory. Password verification incomplete");
- goto out;
- }
- convert_key_to_hex_ascii_for_upgrade((const unsigned char*)passwd,
- strlen(passwd), new_passwd);
- }
- key_index = set_hw_device_encryption_key((const char*)new_passwd,
- (char*) crypt_ftr->crypto_type_name);
- if (key_index >=0) {
- crypt_ftr->failed_decrypt_count = 0;
- SLOGI("Hex password verified...will try to update with Ascii value");
- /* Before updating password, tie that with keymaster to tie with ROT */
-
- if (get_keymaster_hw_fde_passwd(passwd, newpw,
- crypt_ftr->salt, crypt_ftr)) {
- passwd_updated = update_hw_device_encryption_key(new_passwd,
- passwd, (char*)crypt_ftr->crypto_type_name);
- } else {
- passwd_updated = update_hw_device_encryption_key(new_passwd,
- (const char*)newpw, (char*)crypt_ftr->crypto_type_name);
- }
-
- if (passwd_updated >= 0) {
- crypt_ftr->flags |= CRYPT_ASCII_PASSWORD_UPDATED;
- SLOGI("Ascii password recorded and updated");
- } else {
- SLOGI("Passwd verified, could not update...Will try next time");
- }
- } else {
- ++crypt_ftr->failed_decrypt_count;
- }
- free(new_passwd);
- }
- } else {
- if (!ascii_passwd_updated)
- crypt_ftr->flags |= CRYPT_ASCII_PASSWORD_UPDATED;
- }
-out:
- // update footer before leaving
- //put_crypt_ftr_and_key(crypt_ftr);
- return key_index;
-}
-#endif
-
-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);
-}
-
-/* This signs the given object using the keymaster key. */
-static int keymaster_sign_object(struct crypt_mnt_ftr *ftr,
- const unsigned char *object,
- const size_t object_size,
- unsigned char **signature,
- size_t *signature_size)
-{
- SLOGI("TWRP keymaster max API: %i\n", TW_KEYMASTER_MAX_API);
- unsigned char to_sign[RSA_KEY_SIZE_BYTES];
- size_t to_sign_size = sizeof(to_sign);
- memset(to_sign, 0, RSA_KEY_SIZE_BYTES);
-
- // To sign a message with RSA, the message must satisfy two
- // constraints:
- //
- // 1. The message, when interpreted as a big-endian numeric value, must
- // be strictly less than the public modulus of the RSA key. Note
- // that because the most significant bit of the public modulus is
- // guaranteed to be 1 (else it's an (n-1)-bit key, not an n-bit
- // key), an n-bit message with most significant bit 0 always
- // satisfies this requirement.
- //
- // 2. The message must have the same length in bits as the public
- // modulus of the RSA key. This requirement isn't mathematically
- // necessary, but is necessary to ensure consistency in
- // implementations.
- switch (ftr->kdf_type) {
- case KDF_SCRYPT_KEYMASTER_UNPADDED:
- // This is broken: It produces a message which is shorter than
- // the public modulus, failing criterion 2.
- memcpy(to_sign, object, object_size);
- to_sign_size = object_size;
- SLOGI("Signing unpadded object\n");
- break;
- case KDF_SCRYPT_KEYMASTER_BADLY_PADDED:
- // This is broken: Since the value of object is uniformly
- // distributed, it produces a message that is larger than the
- // public modulus with probability 0.25.
- memcpy(to_sign, object, min(RSA_KEY_SIZE_BYTES, object_size));
- SLOGI("Signing end-padded object\n");
- break;
- case KDF_SCRYPT_KEYMASTER:
- // This ensures the most significant byte of the signed message
- // is zero. We could have zero-padded to the left instead, but
- // this approach is slightly more robust against changes in
- // object size. However, it's still broken (but not unusably
- // so) because we really should be using a proper deterministic
- // RSA padding function, such as PKCS1.
- memcpy(to_sign + 1, object, min((size_t)RSA_KEY_SIZE_BYTES - 1, object_size));
- SLOGI("Signing safely-padded object");
- break;
- default:
- SLOGE("Unknown KDF type %d", ftr->kdf_type);
- return -1;
- }
-
- int rc = -1;
-
-#if TW_KEYMASTER_MAX_API >= 1
- keymaster0_device_t *keymaster0_dev = 0;
- keymaster1_device_t *keymaster1_dev = 0;
- keymaster2_device_t *keymaster2_dev = 0;
- if (keymaster_init(&keymaster0_dev, &keymaster1_dev, &keymaster2_dev)) {
-#else
- keymaster_device_t *keymaster0_dev = 0;
- if (keymaster_init(&keymaster0_dev)) {
-#endif
- printf("Failed to init keymaster 0/1\n");
- goto initfail;
- }
- if (keymaster0_dev) {
- keymaster_rsa_sign_params_t params;
- params.digest_type = DIGEST_NONE;
- params.padding_type = PADDING_NONE;
-
- rc = keymaster0_dev->sign_data(keymaster0_dev,
- ¶ms,
- ftr->keymaster_blob,
- ftr->keymaster_blob_size,
- to_sign,
- to_sign_size,
- signature,
- signature_size);
- goto out;
- }
-#if TW_KEYMASTER_MAX_API >= 1
- else if (keymaster1_dev) {
- keymaster_key_blob_t key = { ftr->keymaster_blob, ftr->keymaster_blob_size };
- keymaster_key_param_t params[] = {
- keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE),
- keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
- };
- keymaster_key_param_set_t param_set = { params, sizeof(params)/sizeof(*params) };
- keymaster_operation_handle_t op_handle;
- keymaster_error_t error = keymaster1_dev->begin(keymaster1_dev, KM_PURPOSE_SIGN, &key,
- ¶m_set, NULL /* out_params */,
- &op_handle);
- if (error == KM_ERROR_KEY_RATE_LIMIT_EXCEEDED) {
- // Key usage has been rate-limited. Wait a bit and try again.
- sleep(KEYMASTER_CRYPTFS_RATE_LIMIT);
- error = keymaster1_dev->begin(keymaster1_dev, KM_PURPOSE_SIGN, &key,
- ¶m_set, NULL /* out_params */,
- &op_handle);
- }
- if (error != KM_ERROR_OK) {
- printf("Error starting keymaster signature transaction: %d\n", error);
- rc = -1;
- goto out;
- }
-
- keymaster_blob_t input = { to_sign, to_sign_size };
- size_t input_consumed;
- error = keymaster1_dev->update(keymaster1_dev, op_handle, NULL /* in_params */,
- &input, &input_consumed, NULL /* out_params */,
- NULL /* output */);
- if (error != KM_ERROR_OK) {
- printf("Error sending data to keymaster signature transaction: %d\n", error);
- rc = -1;
- goto out;
- }
- if (input_consumed != to_sign_size) {
- // This should never happen. If it does, it's a bug in the keymaster implementation.
- printf("Keymaster update() did not consume all data.\n");
- keymaster1_dev->abort(keymaster1_dev, op_handle);
- rc = -1;
- goto out;
- }
-
- keymaster_blob_t tmp_sig;
- error = keymaster1_dev->finish(keymaster1_dev, op_handle, NULL /* in_params */,
- NULL /* verify signature */, NULL /* out_params */,
- &tmp_sig);
- if (error != KM_ERROR_OK) {
- printf("Error finishing keymaster signature transaction: %d\n", error);
- rc = -1;
- goto out;
- }
-
- *signature = (uint8_t*)tmp_sig.data;
- *signature_size = tmp_sig.data_length;
- rc = 0;
- }
- else if (keymaster2_dev) {
- keymaster_key_blob_t key = { ftr->keymaster_blob, ftr->keymaster_blob_size };
- keymaster_key_param_t params[] = {
- keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE),
- keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
- };
- keymaster_key_param_set_t param_set = { params, sizeof(params)/sizeof(*params) };
- keymaster_operation_handle_t op_handle;
- keymaster_key_param_t config_params[] = {
- // Set these to crazy values so we don't need to synchronize
- // the recovery with system updates.
- // key upgrades will be required; it will be upgraded in-memory
- keymaster_param_int(KM_TAG_OS_VERSION, 999999),
- keymaster_param_int(KM_TAG_OS_PATCHLEVEL, 209912),
- };
- keymaster_key_param_set_t config_param_set = { config_params, sizeof(config_params)/sizeof(*config_params) };
- keymaster2_dev->configure(keymaster2_dev, &config_param_set);
- keymaster_error_t error = keymaster2_dev->begin(keymaster2_dev, KM_PURPOSE_SIGN, &key,
- ¶m_set, NULL /* out_params */,
- &op_handle);
- if (error == KM_ERROR_KEY_RATE_LIMIT_EXCEEDED) {
- // Key usage has been rate-limited. Wait a bit and try again.
- sleep(KEYMASTER_CRYPTFS_RATE_LIMIT);
- error = keymaster2_dev->begin(keymaster2_dev, KM_PURPOSE_SIGN, &key,
- ¶m_set, NULL /* out_params */,
- &op_handle);
- }
-
- if (error == KM_ERROR_KEY_REQUIRES_UPGRADE) {
- // Upgrade key in-memory if required
- // Do not actually write it back; just keep it in memory
- const keymaster_key_blob_t key_to_upd = key;
- keymaster2_dev->upgrade_key(keymaster2_dev, &key_to_upd, &config_param_set, &key);
- error = keymaster2_dev->begin(keymaster2_dev, KM_PURPOSE_SIGN, &key,
- ¶m_set, NULL /* out_params */,
- &op_handle);
- }
-
- if (error != KM_ERROR_OK) {
- printf("Error starting keymaster signature transaction: %d\n", error);
- rc = -1;
- goto out;
- }
-
- keymaster_blob_t input = { to_sign, to_sign_size };
- size_t input_consumed;
- error = keymaster2_dev->update(keymaster2_dev, op_handle, NULL /* in_params */,
- &input, &input_consumed, NULL /* out_params */,
- NULL /* output */);
- if (error != KM_ERROR_OK) {
- printf("Error sending data to keymaster signature transaction: %d\n", error);
- rc = -1;
- goto out;
- }
- if (input_consumed != to_sign_size) {
- // This should never happen. If it does, it's a bug in the keymaster implementation.
- printf("Keymaster update() did not consume all data.\n");
- keymaster2_dev->abort(keymaster2_dev, op_handle);
- rc = -1;
- goto out;
- }
-
- keymaster_blob_t tmp_sig;
- error = keymaster2_dev->finish(keymaster2_dev, op_handle, NULL /* in_params */,
- NULL, NULL /* verify signature */, NULL /* out_params */,
- &tmp_sig);
- if (error != KM_ERROR_OK) {
- printf("Error finishing keymaster signature transaction: %d\n", error);
- rc = -1;
- goto out;
- }
-
- *signature = (uint8_t*)tmp_sig.data;
- *signature_size = tmp_sig.data_length;
- rc = 0;
- }
-#endif // TW_KEYMASTER_API >= 1
-
- out:
-#if TW_KEYMASTER_MAX_API >= 1
- if (keymaster1_dev)
- keymaster1_close(keymaster1_dev);
-#endif
- if (keymaster0_dev)
-#if TW_KEYMASTER_MAX_API >= 1
- keymaster0_close(keymaster0_dev);
-#else
- keymaster_close(keymaster0_dev);
-#endif
-
- if (rc == 0)
- return 0; // otherwise we'll try for a newer keymaster API
-
-initfail:
-#if TW_KEYMASTER_MAX_API == 3
- return keymaster_sign_object_for_cryptfs_scrypt(ftr->keymaster_blob, ftr->keymaster_blob_size,
- KEYMASTER_CRYPTFS_RATE_LIMIT, to_sign, to_sign_size, signature, signature_size,
- ftr->keymaster_blob, KEYMASTER_BLOB_SIZE, &ftr->keymaster_blob_size);
-#endif //TW_KEYMASTER_MAX_API == 3
-#if TW_KEYMASTER_MAX_API >= 4
- for (int c = 1;c <= 20;c++) { // 20 tries are enough for signing keymaster
- if (c > 2)
- usleep(5000); // if failed in two tries lets rest
- auto result = keymaster_sign_object_for_cryptfs_scrypt(
- ftr->keymaster_blob, ftr->keymaster_blob_size, KEYMASTER_CRYPTFS_RATE_LIMIT, to_sign,
- to_sign_size, signature, signature_size);
- switch (result) {
- case KeymasterSignResult::ok:
- return 0;
- case KeymasterSignResult::upgrade:
- break;
- default:
- return -1;
- }
- SLOGD("Upgrading key\n");
- if (keymaster_upgrade_key_for_cryptfs_scrypt(
- RSA_KEY_SIZE, RSA_EXPONENT, KEYMASTER_CRYPTFS_RATE_LIMIT, ftr->keymaster_blob,
- ftr->keymaster_blob_size, ftr->keymaster_blob, KEYMASTER_BLOB_SIZE,
- &ftr->keymaster_blob_size) != 0) {
- SLOGE("Failed to upgrade key\n");
- return -1;
- }
- /*if (put_crypt_ftr_and_key(ftr) != 0) {
- SLOGE("Failed to write upgraded key to disk");
- }*/
- SLOGD("Key upgraded successfully\n");
- }
-#endif
- return -1;
-}
-
-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) {
- strlcpy(io->name, name, sizeof(io->name));
- }
-}
-
-namespace {
-
-struct CryptoType;
-
-// Use to get the CryptoType in use on this device.
-const CryptoType &get_crypto_type();
-
-struct CryptoType {
- // We should only be constructing CryptoTypes as part of
- // supported_crypto_types[]. We do it via this pseudo-builder pattern,
- // which isn't pure or fully protected as a concession to being able to
- // do it all at compile time. Add new CryptoTypes in
- // supported_crypto_types[] below.
- constexpr CryptoType() : CryptoType(nullptr, nullptr, 0xFFFFFFFF) {}
- constexpr CryptoType set_keysize(uint32_t size) const {
- return CryptoType(this->property_name, this->crypto_name, size);
- }
- constexpr CryptoType set_property_name(const char *property) const {
- return CryptoType(property, this->crypto_name, this->keysize);
- }
- constexpr CryptoType set_crypto_name(const char *crypto) const {
- return CryptoType(this->property_name, crypto, this->keysize);
- }
-
- constexpr const char *get_property_name() const { return property_name; }
- constexpr const char *get_crypto_name() const { return crypto_name; }
- constexpr uint32_t get_keysize() const { return keysize; }
-
- private:
- const char *property_name;
- const char *crypto_name;
- uint32_t keysize;
-
- constexpr CryptoType(const char *property, const char *crypto,
- uint32_t ksize)
- : property_name(property), crypto_name(crypto), keysize(ksize) {}
- friend const CryptoType &get_crypto_type();
- static const CryptoType &get_device_crypto_algorithm();
-};
-
-// We only want to parse this read-only property once. But we need to wait
-// until the system is initialized before we can read it. So we use a static
-// scoped within this function to get it only once.
-const CryptoType &get_crypto_type() {
- static CryptoType crypto_type = CryptoType::get_device_crypto_algorithm();
- return crypto_type;
-}
-
-constexpr CryptoType default_crypto_type = CryptoType()
- .set_property_name("AES-128-CBC")
- .set_crypto_name("aes-cbc-essiv:sha256")
- .set_keysize(16);
-
-constexpr CryptoType supported_crypto_types[] = {
- default_crypto_type,
- CryptoType()
- .set_property_name("Speck128/128-XTS")
- .set_crypto_name("speck128-xts-plain64")
- .set_keysize(32),
- // Add new CryptoTypes here. Order is not important.
-};
-
-
-// ---------- START COMPILE-TIME SANITY CHECK BLOCK -------------------------
-// We confirm all supported_crypto_types have a small enough keysize and
-// had both set_property_name() and set_crypto_name() called.
-
-template <typename T, size_t N>
-constexpr size_t array_length(T (&)[N]) { return N; }
-
-constexpr bool indexOutOfBoundsForCryptoTypes(size_t index) {
- return (index >= array_length(supported_crypto_types));
-}
-
-constexpr bool isValidCryptoType(const CryptoType &crypto_type) {
- return ((crypto_type.get_property_name() != nullptr) &&
- (crypto_type.get_crypto_name() != nullptr) &&
- (crypto_type.get_keysize() <= MAX_KEY_LEN));
-}
-
-// Note in C++11 that constexpr functions can only have a single line.
-// So our code is a bit convoluted (using recursion instead of a loop),
-// but it's asserting at compile time that all of our key lengths are valid.
-constexpr bool validateSupportedCryptoTypes(size_t index) {
- return indexOutOfBoundsForCryptoTypes(index) ||
- (isValidCryptoType(supported_crypto_types[index]) &&
- validateSupportedCryptoTypes(index + 1));
-}
-
-static_assert(validateSupportedCryptoTypes(0),
- "We have a CryptoType with keysize > MAX_KEY_LEN or which was "
- "incompletely constructed.");
-// ---------- END COMPILE-TIME SANITY CHECK BLOCK -------------------------
-
-
-// Don't call this directly, use get_crypto_type(), which caches this result.
-const CryptoType &CryptoType::get_device_crypto_algorithm() {
- constexpr char CRYPT_ALGO_PROP[] = "ro.crypto.fde_algorithm";
- char paramstr[PROPERTY_VALUE_MAX];
-
- property_get(CRYPT_ALGO_PROP, paramstr,
- default_crypto_type.get_property_name());
- for (auto const &ctype : supported_crypto_types) {
- if (strcmp(paramstr, ctype.get_property_name()) == 0) {
- return ctype;
- }
- }
- ALOGE("Invalid name (%s) for %s. Defaulting to %s\n", paramstr,
- CRYPT_ALGO_PROP, default_crypto_type.get_property_name());
- return default_crypto_type;
-}
-
-} // namespace
-
-#define SCRYPT_PROP "ro.crypto.scrypt_params"
-#define SCRYPT_DEFAULTS "15:3:1"
-
-bool parse_scrypt_parameters(const char* paramstr, int *Nf, int *rf, int *pf) {
- int params[3] = {};
- char *token;
- char *saveptr;
- int i;
-
- /*
- * 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(const_cast<char *>(paramstr), ":", &saveptr);
- token != nullptr && i < 3;
- i++, token = strtok_r(nullptr, ":", &saveptr)) {
- char *endptr;
- params[i] = strtol(token, &endptr, 10);
-
- /*
- * Check that there was a valid number and it's 8-bit.
- */
- if ((*token == '\0') || (*endptr != '\0') || params[i] < 0 || params[i] > 255) {
- return false;
- }
- }
- if (token != nullptr) {
- return false;
- }
- *Nf = params[0]; *rf = params[1]; *pf = params[2];
- return true;
-}
-
-uint32_t cryptfs_get_keysize() {
- return get_crypto_type().get_keysize();
-}
-
-const char *cryptfs_get_crypto_name() {
- return get_crypto_type().get_crypto_name();
-}
-
-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];
- int rc = -1;
-
- if (!cached_data) {
- //fs_mgr_get_crypt_info(fstab_default, key_loc, real_blkdev, sizeof(key_loc));
-
- if (!strcmp(key_fname, KEY_IN_FOOTER)) {
- if ( (fd = open(real_blkdev, O_RDWR|O_CLOEXEC)) < 0) {
- SLOGE("Cannot open real block device %s\n", real_blkdev);
- return -1;
- }
-
- unsigned long nr_sec = 0;
- get_blkdev_size(fd, &nr_sec);
- if (nr_sec != 0) {
- /* 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 {
- SLOGE("Cannot get size of block device %s\n", real_blkdev);
- }
- close(fd);
- } else {
- strlcpy(cached_metadata_fname, key_fname, 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;
-}
-
-static int get_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr)
-{
- int fd;
- unsigned int cnt;
- off64_t starting_off;
- int rc = -1;
- char *fname = NULL;
- struct stat statbuf;
-
- if (get_crypt_ftr_info(&fname, &starting_off)) {
- SLOGE("Unable to get crypt_ftr_info\n");
- return -1;
- }
- if (fname[0] != '/') {
- SLOGE("fde::get_crypt_ftr_and_key::Unexpected value for crypto key location: %s\n", fname);
- return -1;
- }
- if ( (fd = open(fname, O_RDWR|O_CLOEXEC)) < 0) {
- SLOGE("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)) {
- SLOGE("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) {
- SLOGE("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)) {
- SLOGE("Cannot read real block device footer\n");
- goto errout;
- }
-
- if (crypt_ftr->magic != CRYPT_MNT_MAGIC) {
- SLOGE("Bad magic for real block device %s\n", fname);
- goto errout;
- }
-
- if (crypt_ftr->major_version != CURRENT_MAJOR_VERSION) {
- SLOGE("Cannot understand major version %d real block device footer; expected %d\n",
- crypt_ftr->major_version, CURRENT_MAJOR_VERSION);
- goto errout;
- }
-
- // We risk buffer overflows with oversized keys, so we just reject them.
- // 0-sized keys are problematic (essentially by-passing encryption), and
- // AES-CBC key wrapping only works for multiples of 16 bytes.
- if ((crypt_ftr->keysize == 0) || ((crypt_ftr->keysize % 16) != 0) ||
- (crypt_ftr->keysize > MAX_KEY_LEN)) {
- SLOGE("Invalid keysize (%u) for block device %s; Must be non-zero, "
- "divisible by 16, and <= %d\n", crypt_ftr->keysize, fname,
- MAX_KEY_LEN);
- goto errout;
- }
-
- if (crypt_ftr->minor_version > CURRENT_MINOR_VERSION) {
- SLOGW("Warning: crypto footer minor version %d, expected <= %d, continuing...\n",
- crypt_ftr->minor_version, CURRENT_MINOR_VERSION);
- }
-
- /* Success! */
- rc = 0;
-
-errout:
- close(fd);
- return rc;
-}
-
-int cryptfs_check_footer()
-{
- int rc = -1;
- struct crypt_mnt_ftr crypt_ftr;
-
- rc = get_crypt_ftr_and_key(&crypt_ftr);
-
- return rc;
-}
-
-/* Convert a binary key of specified length into an ascii hex string equivalent,
- * without the leading 0x and with null termination
- */
-static void convert_key_to_hex_ascii(const 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,
- const unsigned char *master_key, const char *real_blk_name,
- const char *name, int fd, const char *extra_params) {
- alignas(struct dm_ioctl) char buffer[DM_CRYPT_BUF_SIZE];
- struct dm_ioctl *io;
- struct dm_target_spec *tgt;
- char *crypt_params;
- // We need two ASCII characters to represent each byte, and need space for
- // the '\0' terminator.
- char master_key_ascii[MAX_KEY_LEN * 2 + 1];
- size_t buff_offset;
- 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;
- crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
- buff_offset = crypt_params - buffer;
- SLOGI(
- "Creating crypto dev \"%s\"; cipher=%s, keysize=%u, real_dev=%s, len=%llu, params=\"%s\"\n",
- name, crypt_ftr->crypto_type_name, crypt_ftr->keysize, real_blk_name, tgt->length * 512,
- extra_params);
-
-#ifdef CONFIG_HW_DISK_ENCRYPTION
- if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name)) {
- strlcpy(tgt->target_type, "req-crypt",DM_MAX_TYPE_NAME);
- if (is_ice_enabled())
- convert_key_to_hex_ascii(master_key, sizeof(int), master_key_ascii);
- else
- convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
- }
- else {
- convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
- strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME);
- }
- snprintf(crypt_params, sizeof(buffer) - buff_offset, "%s %s 0 %s 0 %s 0",
- crypt_ftr->crypto_type_name, master_key_ascii,
- real_blk_name, extra_params);
-
- SLOGI("target_type = %s", tgt->target_type);
- SLOGI("real_blk_name = %s, extra_params = %s", real_blk_name, extra_params);
-#else
- convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
- strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME);
- snprintf(crypt_params, sizeof(buffer) - buff_offset, "%s %s 0 %s 0 %s",
- crypt_ftr->crypto_type_name, master_key_ascii, real_blk_name,
- extra_params);
-#endif
-
- 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++) {
- int ret = ioctl(fd, DM_TABLE_LOAD, io);
- if (!ret) {
- SLOGI("ioctl err: %d", ret);
- 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;
-
- 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) {
-#ifdef CONFIG_HW_DISK_ENCRYPTION
- if (! strcmp(v->name, "crypt") || ! strcmp(v->name, "req-crypt")) {
-#else
- if (! strcmp(v->name, "crypt")) {
-#endif
- /* 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;
-}
-
-#ifndef CONFIG_HW_DISK_ENCRYPTION
-static std::string extra_params_as_string(const std::vector<std::string>& extra_params_vec) {
- if (extra_params_vec.empty()) return "";
- char temp[10];
- snprintf(temp, sizeof(temp), "%zd", extra_params_vec.size());
- std::string extra_params = temp; //std::to_string(extra_params_vec.size());
- for (const auto& p : extra_params_vec) {
- extra_params.append(" ");
- extra_params.append(p);
- }
- return extra_params;
-}
-#endif
-
-static int create_crypto_blk_dev(struct crypt_mnt_ftr* crypt_ftr, const unsigned char* master_key,
- const char* real_blk_name, char* crypto_blk_name, const char* name,
- uint32_t flags) {
- char buffer[DM_CRYPT_BUF_SIZE];
- struct dm_ioctl* io;
- unsigned int minor;
- int fd = 0;
- int err;
- int retval = -1;
- int version[3];
- int load_count;
-#ifdef CONFIG_HW_DISK_ENCRYPTION
- char encrypted_state[PROPERTY_VALUE_MAX] = {0};
- char progress[PROPERTY_VALUE_MAX] = {0};
- const char *extra_params;
-#else
- std::vector<std::string> extra_params_vec;
-#endif
-
- if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
- SLOGE("Cannot open device-mapper\n");
- goto errout;
- }
-
- io = (struct dm_ioctl*)buffer;
-
- ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
- err = ioctl(fd, DM_DEV_CREATE, io);
- if (err) {
- SLOGE("Cannot create dm-crypt device %s: %s\n", name, strerror(errno));
- 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)) {
- SLOGE("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);
-
-#ifdef CONFIG_HW_DISK_ENCRYPTION
- if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name)) {
- /* Set fde_enabled if either FDE completed or in-progress */
- property_get("ro.crypto.state", encrypted_state, ""); /* FDE completed */
- property_get("vold.encrypt_progress", progress, ""); /* FDE in progress */
- if (!strcmp(encrypted_state, "encrypted") || strcmp(progress, "")) {
- if (is_ice_enabled()) {
- if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE)
- extra_params = "fde_enabled ice allow_encrypt_override";
- else
- extra_params = "fde_enabled ice";
- } else {
- if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE)
- extra_params = "fde_enabled allow_encrypt_override";
- else
- extra_params = "fde_enabled";
- }
- } else {
- if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE)
- extra_params = "fde_enabled allow_encrypt_override";
- else
- extra_params = "fde_enabled";
- }
- } else {
- 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))) {
- if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE)
- extra_params = "2 allow_discards allow_encrypt_override";
- else
- extra_params = "1 allow_discards";
- SLOGI("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);
-#else
- 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_vec.push_back(std::string("allow_discards")); // Used to be extra_params_vec.emplace_back("allow_discards"); but this won't compile in 5.1 trees
- }
- }
- if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE) {
- extra_params_vec.push_back(std::string("allow_encrypt_override")); // Used to be extra_params_vec.emplace_back("allow_encrypt_override"); but this won't compile in 5.1 trees
- }
- load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name, fd,
- extra_params_as_string(extra_params_vec).c_str());
-#endif
- if (load_count < 0) {
- SLOGE("Cannot load dm-crypt mapping table.\n");
- goto errout;
- } else if (load_count > 1) {
- SLOGI("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)) {
- SLOGE("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;
-}
-
-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|O_CLOEXEC)) < 0 ) {
- SLOGE("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)) {
- SLOGE("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 int pbkdf2(const char *passwd, const unsigned char *salt,
- unsigned char *ikey, void *params UNUSED)
-{
- SLOGI("Using pbkdf2 for cryptfs KDF\n");
-
- /* Turn the password into a key and IV that can decrypt the master key */
- return PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), salt, SALT_LEN,
- HASH_COUNT, INTERMEDIATE_BUF_SIZE,
- ikey) != 1;
-}
-
-static int scrypt(const char *passwd, const unsigned char *salt,
- unsigned char *ikey, void *params)
-{
- SLOGI("Using scrypt for cryptfs KDF\n");
-
- 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((const uint8_t*)passwd, strlen(passwd),
- salt, SALT_LEN, N, r, p, ikey,
- INTERMEDIATE_BUF_SIZE);
-
- return 0;
-}
-
-static int scrypt_keymaster(const char *passwd, const unsigned char *salt,
- unsigned char *ikey, void *params)
-{
- SLOGI("Using scrypt with keymaster for cryptfs KDF\n");
-
- int rc;
- size_t signature_size;
- unsigned char* signature;
- 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;
-
- rc = crypto_scrypt((const uint8_t*)passwd, strlen(passwd),
- salt, SALT_LEN, N, r, p, ikey,
- INTERMEDIATE_BUF_SIZE);
-
- if (rc) {
- SLOGE("scrypt failed");
- return -1;
- }
-
- if (keymaster_sign_object(ftr, ikey, INTERMEDIATE_BUF_SIZE,
- &signature, &signature_size)) {
- SLOGE("Keymaster signing failed");
- return -1;
- }
-
- rc = crypto_scrypt(signature, signature_size, salt, SALT_LEN,
- N, r, p, ikey, INTERMEDIATE_BUF_SIZE);
- free(signature);
-
- if (rc) {
- SLOGE("scrypt failed");
- return -1;
- }
-
- return 0;
-}
-
-static int decrypt_master_key_aux(const char *passwd, unsigned char *salt,
- const unsigned char *encrypted_master_key,
- size_t keysize,
- unsigned char *decrypted_master_key,
- kdf_func kdf, void *kdf_params,
- unsigned char** intermediate_key,
- size_t* intermediate_key_size)
-{
- unsigned char ikey[INTERMEDIATE_BUF_SIZE] = { 0 };
- EVP_CIPHER_CTX d_ctx;
- int decrypted_len, final_len;
-
- /* Turn the password into an intermediate key and IV that can decrypt the
- master key */
- if (kdf(passwd, salt, ikey, kdf_params)) {
- SLOGE("kdf failed");
- return -1;
- }
-
- /* Initialize the decryption engine */
- EVP_CIPHER_CTX_init(&d_ctx);
- if (! EVP_DecryptInit_ex(&d_ctx, EVP_aes_128_cbc(), NULL, ikey, ikey+INTERMEDIATE_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, keysize)) {
- return -1;
- }
- if (! EVP_DecryptFinal_ex(&d_ctx, decrypted_master_key + decrypted_len, &final_len)) {
- return -1;
- }
-
- if (decrypted_len + final_len != static_cast<int>(keysize)) {
- return -1;
- }
-
- /* Copy intermediate key if needed by params */
- if (intermediate_key && intermediate_key_size) {
- *intermediate_key = (unsigned char*) malloc(INTERMEDIATE_KEY_LEN_BYTES);
- if (*intermediate_key) {
- memcpy(*intermediate_key, ikey, INTERMEDIATE_KEY_LEN_BYTES);
- *intermediate_key_size = INTERMEDIATE_KEY_LEN_BYTES;
- }
- }
-
- EVP_CIPHER_CTX_cleanup(&d_ctx);
-
- return 0;
-}
-
-static void get_kdf_func(struct crypt_mnt_ftr *ftr, kdf_func *kdf, void** kdf_params)
-{
- if (ftr->kdf_type == KDF_SCRYPT_KEYMASTER) {
- *kdf = scrypt_keymaster;
- *kdf_params = ftr;
- } else if (ftr->kdf_type == KDF_SCRYPT) {
- *kdf = scrypt;
- *kdf_params = ftr;
- } else {
- *kdf = pbkdf2;
- *kdf_params = NULL;
- }
-}
-
-static int decrypt_master_key(const char *passwd, unsigned char *decrypted_master_key,
- struct crypt_mnt_ftr *crypt_ftr,
- unsigned char** intermediate_key,
- size_t* intermediate_key_size)
-{
- kdf_func kdf;
- void *kdf_params;
- int ret;
-
- get_kdf_func(crypt_ftr, &kdf, &kdf_params);
- ret = decrypt_master_key_aux(passwd, crypt_ftr->salt, crypt_ftr->master_key,
- crypt_ftr->keysize,
- decrypted_master_key, kdf, kdf_params,
- intermediate_key, intermediate_key_size);
- if (ret != 0) {
- SLOGW("failure decrypting master key");
- }
-
- return ret;
-}
-
-#ifdef CONFIG_HW_DISK_ENCRYPTION
-static int test_mount_hw_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
- const char *passwd, const char *mount_point, const 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];
- unsigned int orig_failed_decrypt_count;
- int rc = 0;
-
- SLOGD("crypt_ftr->fs_size = %lld\n", crypt_ftr->fs_size);
- orig_failed_decrypt_count = crypt_ftr->failed_decrypt_count;
-
- //fs_mgr_get_crypt_info(fstab_default, 0, real_blkdev, sizeof(real_blkdev));
-
- int key_index = 0;
- if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name)) {
- key_index = verify_and_update_hw_fde_passwd(passwd, crypt_ftr);
- if (key_index < 0) {
- rc = -1;
- goto errout;
- }
- else {
- if (is_ice_enabled()) {
-#ifndef CONFIG_HW_DISK_ENCRYPT_PERF
- if (create_crypto_blk_dev(crypt_ftr, (unsigned char*)&key_index,
- real_blkdev, crypto_blkdev, label, 0)) {
- SLOGE("Error creating decrypted block device");
- rc = -1;
- goto errout;
- }
-#endif
- } else {
- if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
- real_blkdev, crypto_blkdev, label, 0)) {
- SLOGE("Error creating decrypted block device");
- rc = -1;
- goto errout;
- }
- }
- }
- }
-
- if (rc == 0) {
- /* Save the name of the crypto block device
- * so we can mount it when restarting the framework. */
-#ifdef CONFIG_HW_DISK_ENCRYPT_PERF
- if (!is_ice_enabled())
-#endif
- property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev);
- master_key_saved = 1;
- }
-
- errout:
- return rc;
-}
-#endif
-
-static int try_mount_multiple_fs(const char *crypto_blkdev,
- const char *mount_point,
- const char *file_system)
-{
- if (!mount(crypto_blkdev, mount_point, file_system, 0, NULL))
- return 0;
- if (strcmp(file_system, "ext4") &&
- !mount(crypto_blkdev, mount_point, "ext4", 0, NULL))
- return 0;
- if (strcmp(file_system, "f2fs") &&
- !mount(crypto_blkdev, mount_point, "f2fs", 0, NULL))
- return 0;
- return 1;
-}
-
-static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
- const char *passwd, const char *mount_point, const char *label)
-{
- unsigned char decrypted_master_key[MAX_KEY_LEN];
- char crypto_blkdev[MAXPATHLEN];
- //char real_blkdev[MAXPATHLEN];
- char tmp_mount_point[64];
- unsigned int orig_failed_decrypt_count;
- int rc;
- int use_keymaster = 0;
- unsigned char* intermediate_key = 0;
- size_t intermediate_key_size = 0;
- int N = 1 << crypt_ftr->N_factor;
- int r = 1 << crypt_ftr->r_factor;
- int p = 1 << crypt_ftr->p_factor;
-
- SLOGD("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) ) {
- if (decrypt_master_key(passwd, decrypted_master_key, crypt_ftr,
- &intermediate_key, &intermediate_key_size)) {
- SLOGE("Failed to decrypt master key\n");
- rc = -1;
- goto errout;
- }
- }
-
- //fs_mgr_get_crypt_info(fstab_default, 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, real_blkdev, crypto_blkdev, label, 0)) {
- SLOGE("Error creating decrypted block device\n");
- rc = -1;
- goto errout;
- }
-
- /* Work out if the problem is the password or the data */
- unsigned char scrypted_intermediate_key[sizeof(crypt_ftr->
- scrypted_intermediate_key)];
-
- rc = crypto_scrypt(intermediate_key, intermediate_key_size,
- crypt_ftr->salt, sizeof(crypt_ftr->salt),
- N, r, p, scrypted_intermediate_key,
- sizeof(scrypted_intermediate_key));
-
- // Does the key match the crypto footer?
- if (rc == 0 && memcmp(scrypted_intermediate_key,
- crypt_ftr->scrypted_intermediate_key,
- sizeof(scrypted_intermediate_key)) == 0) {
- SLOGI("Password matches");
- rc = 0;
- } else {
- /* Try mounting the file system anyway, just in case the problem's with
- * the footer, not the key. */
- snprintf(tmp_mount_point, sizeof(tmp_mount_point), "%s/tmp_mnt",
- mount_point);
- mkdir(tmp_mount_point, 0755);
- if (try_mount_multiple_fs(crypto_blkdev, tmp_mount_point, file_system)) {
- SLOGE("Error temp mounting decrypted block device\n");
- delete_crypto_blk_dev(label);
-
- rc = -1;
- } else {
- /* Success! */
- SLOGI("Password did not match but decrypted drive mounted - continue");
- umount(tmp_mount_point);
- rc = 0;
- }
- }
-
- if (rc == 0) {
- /* 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, crypt_ftr->keysize);
- saved_mount_point = strdup(mount_point);
- master_key_saved = 1;
- SLOGD("%s(): Master key saved\n", __FUNCTION__);
- rc = 0;
- }
-
- errout:
- if (intermediate_key) {
- memset(intermediate_key, 0, intermediate_key_size);
- free(intermediate_key);
- }
- return rc;
-}
-
-/*
- * Called by vold when it's asked to mount an encrypted external
- * storage volume. The incoming partition has no crypto header/footer,
- * as any metadata is been stored in a separate, small partition. We
- * assume it must be using our same crypt type and keysize.
- *
- * out_crypto_blkdev must be MAXPATHLEN.
- */
-int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev,
- const unsigned char* key, int keysize, char* out_crypto_blkdev) {
- int fd = open(real_blkdev, O_RDONLY|O_CLOEXEC);
- if (fd == -1) {
- SLOGE("Failed to open %s: %s", real_blkdev, strerror(errno));
- return -1;
- }
-
- unsigned long nr_sec = 0;
- get_blkdev_size(fd, &nr_sec);
- close(fd);
-
- if (nr_sec == 0) {
- SLOGE("Failed to get size of %s: %s", real_blkdev, strerror(errno));
- return -1;
- }
-
- struct crypt_mnt_ftr ext_crypt_ftr;
- memset(&ext_crypt_ftr, 0, sizeof(ext_crypt_ftr));
- ext_crypt_ftr.fs_size = nr_sec;
- ext_crypt_ftr.keysize = cryptfs_get_keysize();
- strlcpy((char*) ext_crypt_ftr.crypto_type_name, cryptfs_get_crypto_name(),
- MAX_CRYPTO_TYPE_NAME_LEN);
- uint32_t flags = 0;
- /*if (e4crypt_is_native() &&
- android::base::GetBoolProperty("ro.crypto.allow_encrypt_override", false))
- flags |= CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE;*/
-
- return create_crypto_blk_dev(&ext_crypt_ftr, key, real_blkdev, out_crypto_blkdev, label, flags);
-}
-
-/*
- * Called by vold when it's asked to unmount an encrypted external
- * storage volume.
- */
-int cryptfs_revert_ext_volume(const char* label) {
- return delete_crypto_blk_dev(label);
-}
-
-int check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr)
-{
- char encrypted_state[PROPERTY_VALUE_MAX];
- property_get("ro.crypto.state", encrypted_state, "");
- if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) {
- SLOGE("encrypted fs already validated or not running with encryption,"
- " aborting");
- return -1;
- }
-
- if (get_crypt_ftr_and_key(crypt_ftr)) {
- SLOGE("Error getting crypt footer and key");
- return -1;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_HW_DISK_ENCRYPTION
-int cryptfs_check_passwd_hw(const char* passwd)
-{
- struct crypt_mnt_ftr crypt_ftr;
- int rc;
- unsigned char master_key[KEY_LEN_BYTES];
- /* get key */
- if (get_crypt_ftr_and_key(&crypt_ftr)) {
- SLOGE("Error getting crypt footer and key");
- return -1;
- }
-
- /*
- * in case of manual encryption (from GUI), the encryption is done with
- * default password
- */
- if (crypt_ftr.flags & CRYPT_FORCE_COMPLETE) {
- /* compare scrypted_intermediate_key with stored scrypted_intermediate_key
- * which was created with actual password before reboot.
- */
- rc = cryptfs_get_master_key(&crypt_ftr, passwd, master_key);
- if (rc) {
- SLOGE("password doesn't match");
- return rc;
- }
-
- rc = test_mount_hw_encrypted_fs(&crypt_ftr, DEFAULT_PASSWORD,
- DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
-
- if (rc) {
- SLOGE("Default password did not match on reboot encryption");
- return rc;
- }
- } else {
- rc = test_mount_hw_encrypted_fs(&crypt_ftr, passwd,
- DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
- SLOGE("test mount returned %i\n", rc);
- }
-
- return rc;
-}
-#endif
-
-int cryptfs_check_passwd(const char *passwd)
-{
- /*if (e4crypt_is_native()) {
- SLOGE("cryptfs_check_passwd not valid for file encryption");
- return -1;
- }*/
-
- struct crypt_mnt_ftr crypt_ftr;
- int rc;
-
- rc = check_unmounted_and_get_ftr(&crypt_ftr);
- if (rc) {
- SLOGE("Could not get footer");
- return rc;
- }
-
-#ifdef CONFIG_HW_DISK_ENCRYPTION
- if (is_hw_disk_encryption((char*)crypt_ftr.crypto_type_name))
- return cryptfs_check_passwd_hw(passwd);
-#endif
-
- rc = test_mount_encrypted_fs(&crypt_ftr, passwd,
- DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
-
- if (rc) {
- SLOGE("Password did not match");
- return rc;
- }
-
- if (crypt_ftr.flags & CRYPT_FORCE_COMPLETE) {
- // Here we have a default actual password but a real password
- // we must test against the scrypted value
- // First, we must delete the crypto block device that
- // test_mount_encrypted_fs leaves behind as a side effect
- delete_crypto_blk_dev(CRYPTO_BLOCK_DEVICE);
- rc = test_mount_encrypted_fs(&crypt_ftr, DEFAULT_PASSWORD,
- DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
- if (rc) {
- SLOGE("Default password did not match on reboot encryption");
- return rc;
- }
- }
-
- return rc;
-}
-
-int cryptfs_verify_passwd(const char *passwd)
-{
- struct crypt_mnt_ftr crypt_ftr;
- unsigned char decrypted_master_key[MAX_KEY_LEN];
- char encrypted_state[PROPERTY_VALUE_MAX];
- int rc;
-
- property_get("ro.crypto.state", encrypted_state, "");
- if (strcmp(encrypted_state, "encrypted") ) {
- SLOGE("device not encrypted, aborting");
- return -2;
- }
-
- if (!master_key_saved) {
- SLOGE("encrypted fs not yet mounted, aborting");
- return -1;
- }
-
- if (!saved_mount_point) {
- SLOGE("encrypted fs failed to save mount point, aborting");
- return -1;
- }
-
- if (get_crypt_ftr_and_key(&crypt_ftr)) {
- SLOGE("Error getting crypt footer and key\n");
- return -1;
- }
-
- if (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) {
- /* If the device has no password, then just say the password is valid */
- rc = 0;
- } else {
-#ifdef CONFIG_HW_DISK_ENCRYPTION
- if(is_hw_disk_encryption((char*)crypt_ftr.crypto_type_name)) {
- if (verify_hw_fde_passwd(passwd, &crypt_ftr) >= 0)
- rc = 0;
- else
- rc = -1;
- } else {
- decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
- 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;
- }
- }
-#else
- decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
- 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;
- }
-#endif
- }
-
- return rc;
-}
-
-/* Returns type of the password, default, pattern, pin or password.
- */
-int cryptfs_get_password_type(void)
-{
- struct crypt_mnt_ftr crypt_ftr;
-
- if (get_crypt_ftr_and_key(&crypt_ftr)) {
- SLOGE("Error getting crypt footer and key\n");
- return -1;
- }
-
- if (crypt_ftr.flags & CRYPT_INCONSISTENT_STATE) {
- return -1;
- }
-
- return crypt_ftr.crypt_type;
-}
-
-int cryptfs_get_master_key(struct crypt_mnt_ftr* ftr, const char* password,
- unsigned char* master_key)
-{
- int rc;
-
- unsigned char* intermediate_key = 0;
- size_t intermediate_key_size = 0;
-
- if (password == 0 || *password == 0) {
- password = DEFAULT_PASSWORD;
- }
-
- rc = decrypt_master_key(password, master_key, ftr, &intermediate_key,
- &intermediate_key_size);
-
- if (rc) {
- SLOGE("Can't calculate intermediate key");
- return rc;
- }
-
- int N = 1 << ftr->N_factor;
- int r = 1 << ftr->r_factor;
- int p = 1 << ftr->p_factor;
-
- unsigned char scrypted_intermediate_key[sizeof(ftr->scrypted_intermediate_key)];
-
- rc = crypto_scrypt(intermediate_key, intermediate_key_size,
- ftr->salt, sizeof(ftr->salt), N, r, p,
- scrypted_intermediate_key,
- sizeof(scrypted_intermediate_key));
-
- free(intermediate_key);
-
- if (rc) {
- SLOGE("Can't scrypt intermediate key");
- return rc;
- }
-
- return memcmp(scrypted_intermediate_key, ftr->scrypted_intermediate_key,
- intermediate_key_size);
-}
-
diff --git a/crypto/fde/cryptfs.h b/crypto/fde/cryptfs.h
deleted file mode 100644
index c67113a..0000000
--- a/crypto/fde/cryptfs.h
+++ /dev/null
@@ -1,208 +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.
- */
-
-#ifndef ANDROID_VOLD_CRYPTFS_H
-#define ANDROID_VOLD_CRYPTFS_H
-
-/* 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 <stdbool.h>
-#include <stdint.h>
-#include <cutils/properties.h>
-
-/* The current cryptfs version */
-#define CURRENT_MAJOR_VERSION 1
-#define CURRENT_MINOR_VERSION 3
-
-#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
-#define SCRYPT_LEN 32
-
-/* definitions of flags in the structure below */
-#define CRYPT_MNT_KEY_UNENCRYPTED 0x1 /* The key for the partition is not encrypted. */
-#define CRYPT_ENCRYPTION_IN_PROGRESS 0x2 /* Encryption partially completed,
- encrypted_upto valid*/
-#define CRYPT_INCONSISTENT_STATE 0x4 /* Set when starting encryption, clear when
- exit cleanly, either through success or
- correctly marked partial encryption */
-#define CRYPT_DATA_CORRUPT 0x8 /* Set when encryption is fine, but the
- underlying volume is corrupt */
-#define CRYPT_FORCE_ENCRYPTION 0x10 /* Set when it is time to encrypt this
- volume on boot. Everything in this
- structure is set up correctly as
- though device is encrypted except
- that the master key is encrypted with the
- default password. */
-#define CRYPT_FORCE_COMPLETE 0x20 /* Set when the above encryption cycle is
- complete. On next cryptkeeper entry, match
- the password. If it matches fix the master
- key and remove this flag. */
-#ifdef CONFIG_HW_DISK_ENCRYPTION
-/* This flag is used to transition from L->M upgrade. L release passed
- * a byte for every nible of user password while M release is passing
- * ascii value of user password.
- * Random flag value is chosen so that it does not conflict with other use cases
- */
-#define CRYPT_ASCII_PASSWORD_UPDATED 0x1000
-#endif
-
-/* Allowed values for type in the structure below */
-#define CRYPT_TYPE_PASSWORD 0 /* master_key is encrypted with a password
- * Must be zero to be compatible with pre-L
- * devices where type is always password.*/
-#define CRYPT_TYPE_DEFAULT 1 /* master_key is encrypted with default
- * password */
-#define CRYPT_TYPE_PATTERN 2 /* master_key is encrypted with a pattern */
-#define CRYPT_TYPE_PIN 3 /* master_key is encrypted with a pin */
-#define CRYPT_TYPE_MAX_TYPE 3 /* type cannot be larger than this value */
-
-#define CRYPT_MNT_MAGIC 0xD0B5B1C4
-#define PERSIST_DATA_MAGIC 0xE950CD44
-
-/* Key Derivation Function algorithms */
-#define KDF_PBKDF2 1
-#define KDF_SCRYPT 2
-/* Algorithms 3 & 4 deprecated before shipping outside of google, so removed */
-#define KDF_SCRYPT_KEYMASTER_UNPADDED 3
-#define KDF_SCRYPT_KEYMASTER_BADLY_PADDED 4
-#define KDF_SCRYPT_KEYMASTER 5
-
-/* Maximum allowed keymaster blob size. */
-#define KEYMASTER_BLOB_SIZE 2048
-
-/* __le32 and __le16 defined in system/extras/ext4_utils/ext4_utils.h */
-#define __le8 unsigned char
-
-#if !defined(SHA256_DIGEST_LENGTH)
-#define SHA256_DIGEST_LENGTH 32
-#endif
-
-struct crypt_mnt_ftr {
- __le32 magic; /* See above */
- __le16 major_version;
- __le16 minor_version;
- __le32 ftr_size; /* in bytes, not including key following */
- __le32 flags; /* See above */
- __le32 keysize; /* in bytes */
- __le32 crypt_type; /* how master_key is encrypted. Must be a
- * CRYPT_TYPE_XXX value */
- __le64 fs_size; /* Size of the encrypted fs, in 512 byte sectors */
- __le32 failed_decrypt_count; /* count of # of failed attempts to decrypt and
- mount, set to 0 on successful mount */
- unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption
- needed to decrypt this
- partition, null terminated */
- __le32 spare2; /* ignored */
- unsigned char master_key[MAX_KEY_LEN]; /* The encrypted key for decrypting the filesystem */
- unsigned char salt[SALT_LEN]; /* The salt used for this encryption */
- __le64 persist_data_offset[2]; /* Absolute offset to both copies of crypt_persist_data
- * on device with that info, either the footer of the
- * real_blkdevice or the metadata partition. */
-
- __le32 persist_data_size; /* The number of bytes allocated to each copy of the
- * persistent data table*/
-
- __le8 kdf_type; /* The key derivation function used. */
-
- /* scrypt parameters. See www.tarsnap.com/scrypt/scrypt.pdf */
- __le8 N_factor; /* (1 << N) */
- __le8 r_factor; /* (1 << r) */
- __le8 p_factor; /* (1 << p) */
- __le64 encrypted_upto; /* If we are in state CRYPT_ENCRYPTION_IN_PROGRESS and
- we have to stop (e.g. power low) this is the last
- encrypted 512 byte sector.*/
- __le8 hash_first_block[SHA256_DIGEST_LENGTH]; /* When CRYPT_ENCRYPTION_IN_PROGRESS
- set, hash of first block, used
- to validate before continuing*/
-
- /* key_master key, used to sign the derived key which is then used to generate
- * the intermediate key
- * This key should be used for no other purposes! We use this key to sign unpadded
- * data, which is acceptable but only if the key is not reused elsewhere. */
- __le8 keymaster_blob[KEYMASTER_BLOB_SIZE];
- __le32 keymaster_blob_size;
-
- /* Store scrypt of salted intermediate key. When decryption fails, we can
- check if this matches, and if it does, we know that the problem is with the
- drive, and there is no point in asking the user for more passwords.
-
- Note that if any part of this structure is corrupt, this will not match and
- we will continue to believe the user entered the wrong password. In that
- case the only solution is for the user to enter a password enough times to
- force a wipe.
-
- Note also that there is no need to worry about migration. If this data is
- wrong, we simply won't recognise a right password, and will continue to
- prompt. On the first password change, this value will be populated and
- then we will be OK.
- */
- unsigned char scrypted_intermediate_key[SCRYPT_LEN];
-
- /* sha of this structure with this element set to zero
- Used when encrypting on reboot to validate structure before doing something
- fatal
- */
- unsigned char sha256[SHA256_DIGEST_LENGTH];
-};
-
-#define DATA_MNT_POINT "/data"
-
-/* Return values for cryptfs_crypto_complete */
-#define CRYPTO_COMPLETE_NOT_ENCRYPTED 1
-#define CRYPTO_COMPLETE_ENCRYPTED 0
-#define CRYPTO_COMPLETE_BAD_METADATA (-1)
-#define CRYPTO_COMPLETE_PARTIAL (-2)
-#define CRYPTO_COMPLETE_INCONSISTENT (-3)
-#define CRYPTO_COMPLETE_CORRUPT (-4)
-
-/* Return values for cryptfs_enable_inplace*() */
-#define ENABLE_INPLACE_OK 0
-#define ENABLE_INPLACE_ERR_OTHER (-1)
-#define ENABLE_INPLACE_ERR_DEV (-2) /* crypto_blkdev issue */
-
-typedef int (*kdf_func)(const char* passwd, const unsigned char* salt, unsigned char* ikey,
- void* params);
-
-int cryptfs_check_passwd(const char* pw);
-int cryptfs_verify_passwd(const char* pw);
-int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const unsigned char* key, int keysize, char* out_crypto_blkdev);
-int cryptfs_revert_ext_volume(const char* label);
-int cryptfs_get_password_type(void);
-
-uint32_t cryptfs_get_keysize();
-const char* cryptfs_get_crypto_name();
-
-void set_partition_data(const char* block_device, const char* key_location, const char* fs);
-int cryptfs_check_footer();
-int delete_crypto_blk_dev(const char *name);
-
-#endif /* ANDROID_VOLD_CRYPTFS_H */
diff --git a/crypto/fde/main.cpp b/crypto/fde/main.cpp
deleted file mode 100644
index 7051a6d..0000000
--- a/crypto/fde/main.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <linux/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <inttypes.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 <errno.h>
-#include <linux/kdev_t.h>
-#include <time.h>
-#include "cryptfs.h"
-#include "cutils/properties.h"
-#include "crypto_scrypt.h"
-
-void usage() {
- printf(" Usage:\n");
- printf(" twrpdec /path/to/userdata /path/to/metadata filesystem password\n");
- printf("\n");
- printf(" The metadata path is the path to the footer. If no metadata\n");
- printf(" partition is present then use footer for this argument.\n");
- printf("\n");
- printf(" Example:\n");
- printf(" twrpdec /dev/block/bootdevice/by-name/userdata footer ext4 0000\n");
-}
-
-int main(int argc, char **argv) {
- if (argc != 5) {
- usage();
- return -1;
- }
- set_partition_data(argv[1], argv[2], argv[3]);
- //int ret = cryptfs_check_passwd("30303030");
- int ret = cryptfs_check_passwd(argv[4]);
- return 0;
-}
diff --git a/crypto/fscrypt/Android.mk b/crypto/fscrypt/Android.mk
deleted file mode 100755
index d9fb6ef..0000000
--- a/crypto/fscrypt/Android.mk
+++ /dev/null
@@ -1,87 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-ifeq ($(TW_INCLUDE_CRYPTO), true)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libtwrpfscrypt
-LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS := -Wno-unused-variable -Wno-sign-compare -Wno-unused-parameter -Wno-comment -Wno-missing-field-initializers \
- -DHAVE_LIBKEYUTILS -std=gnu++2a -Wno-macro-redefined -Wno-unused-function -fpic
-LOCAL_SRC_FILES := FsCrypt.cpp Decrypt.cpp ScryptParameters.cpp fscrypt_policy.cpp Utils.cpp HashPassword.cpp \
- KeyUtil.cpp Keymaster.cpp KeyStorage.cpp MetadataCrypt.cpp KeyBuffer.cpp \
- Process.cpp EncryptInplace.cpp Weaver1.cpp cryptfs.cpp Checkpoint.cpp CryptoType.cpp VoldUtil.cpp
-LOCAL_SHARED_LIBRARIES := libselinux libc libc++ libext4_utils libbase libcrypto libcutils \
-libkeymaster_messages libhardware libprotobuf-cpp-lite libfscrypt android.hardware.confirmationui@1.0 \
-android.hardware.keymaster@3.0 libkeystore_binder libhidlbase libutils libbinder android.hardware.gatekeeper@1.0 \
-libfs_mgr android.hardware.keymaster@4.0 android.hardware.keymaster@4.1 libkeymaster4support libkeymaster4_1support \
-libf2fs_sparseblock libkeystore_parcelables libkeystore_aidl android.hardware.weaver@1.0 libkeyutils liblog libhwbinder \
-libchrome android.hardware.boot@1.0 libbootloader_message
-LOCAL_STATIC_LIBRARIES := libscrypt_static libvold_binder libc++fs
-LOCAL_C_INCLUDES := system/extras/ext4_utils \
- system/extras/ext4_utils/include/ext4_utils \
- external/scrypt/lib/crypto \
- system/security/keystore/include \
- hardware/libhardware/include/hardware \
- system/security/softkeymaster/include/keymaster \
- system/keymaster/include \
- system/extras/libfscrypt/include \
- system/core/fs_mgr/libfs_avb/include/ \
- system/core/fs_mgr/include_fstab/ \
- system/core/fs_mgr/include/ \
- system/core/fs_mgr/libdm/include/ \
- system/core/fs_mgr/liblp/include/ \
- system/gsid/include/ \
- system/core/init/ \
- system/vold/model \
- system/vold/ \
- system/extras/f2fs_utils/ \
- bootable/recovery/bootloader_message/include
-
-ifeq ($(TW_USE_FSCRYPT_POLICY), 1)
- LOCAL_CFLAGS += -DUSE_FSCRYPT_POLICY_V1
-else
- LOCAL_CFLAGS += -DUSE_FSCRYPT_POLICY_V2
-endif
-
-ifneq ($(wildcard hardware/libhardware/include/hardware/keymaster0.h),)
- LOCAL_CFLAGS += -DTW_CRYPTO_HAVE_KEYMASTERX
- LOCAL_C_INCLUDES += external/boringssl/src/include
-endif
-
-LOCAL_REQUIRED_MODULES := keystore_auth keystore
-LOCAL_CLANG := true
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := fscryptpolicyget
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/bin
-LOCAL_C_INCLUDES += system/extras/libfscrypt/include
-LOCAL_SRC_FILES := fscryptpolicyget.cpp
-LOCAL_SHARED_LIBRARIES := libtwrpfscrypt
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := twrpfbe
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/bin
-LOCAL_SRC_FILES := main.cpp
-LOCAL_SHARED_LIBRARIES := libtwrpfscrypt
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := keystore_auth
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/bin
-LOCAL_SRC_FILES := keystore_auth.cpp
-LOCAL_SHARED_LIBRARIES := libc libkeystore_binder libutils libbinder liblog
-LOCAL_CFLAGS += -DUSE_SECURITY_NAMESPACE
-LOCAL_SHARED_LIBRARIES += libkeystore_aidl
-
-include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/crypto/fscrypt/Checkpoint.cpp b/crypto/fscrypt/Checkpoint.cpp
deleted file mode 100644
index fac0d9f..0000000
--- a/crypto/fscrypt/Checkpoint.cpp
+++ /dev/null
@@ -1,744 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#define LOG_TAG "Checkpoint"
-#include "Checkpoint.h"
-#include "VoldUtil.h"
-#include "VolumeManager.h"
-
-#include <fstream>
-#include <list>
-#include <memory>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/parseint.h>
-#include <android-base/properties.h>
-#include <android-base/unique_fd.h>
-#include <android/hardware/boot/1.0/IBootControl.h>
-#include <cutils/android_reboot.h>
-#include <fcntl.h>
-#include <fs_mgr.h>
-#include <linux/fs.h>
-#include <mntent.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <unistd.h>
-
-using android::base::GetBoolProperty;
-using android::base::GetUintProperty;
-using android::base::SetProperty;
-using android::binder::Status;
-using android::fs_mgr::Fstab;
-using android::fs_mgr::ReadDefaultFstab;
-using android::fs_mgr::ReadFstabFromFile;
-using android::hardware::hidl_string;
-using android::hardware::boot::V1_0::BoolResult;
-using android::hardware::boot::V1_0::CommandResult;
-using android::hardware::boot::V1_0::IBootControl;
-using android::hardware::boot::V1_0::Slot;
-
-
-namespace {
-const std::string kMetadataCPFile = "/metadata/vold/checkpoint";
-
-android::binder::Status error(const std::string& msg) {
- PLOG(ERROR) << msg;
- return android::binder::Status::fromServiceSpecificError(errno, android::String8(msg.c_str()));
-}
-
-android::binder::Status error(int error, const std::string& msg) {
- LOG(ERROR) << msg;
- return android::binder::Status::fromServiceSpecificError(error, android::String8(msg.c_str()));
-}
-
-bool setBowState(std::string const& block_device, std::string const& state) {
- std::string bow_device = fs_mgr_find_bow_device(block_device);
- if (bow_device.empty()) return false;
-
- if (!android::base::WriteStringToFile(state, bow_device + "/bow/state")) {
- PLOG(ERROR) << "Failed to write to file " << bow_device + "/bow/state";
- return false;
- }
-
- return true;
-}
-
-} // namespace
-
-Status cp_supportsCheckpoint(bool& result) {
- result = false;
-
- for (const auto& entry : fstab_default) {
- if (entry.fs_mgr_flags.checkpoint_blk || entry.fs_mgr_flags.checkpoint_fs) {
- result = true;
- return Status::ok();
- }
- }
- return Status::ok();
-}
-
-Status cp_supportsBlockCheckpoint(bool& result) {
- result = false;
-
- for (const auto& entry : fstab_default) {
- if (entry.fs_mgr_flags.checkpoint_blk) {
- result = true;
- return Status::ok();
- }
- }
- return Status::ok();
-}
-
-Status cp_supportsFileCheckpoint(bool& result) {
- result = false;
-
- for (const auto& entry : fstab_default) {
- if (entry.fs_mgr_flags.checkpoint_fs) {
- result = true;
- return Status::ok();
- }
- }
- return Status::ok();
-}
-
-Status cp_startCheckpoint(int retry) {
- bool result;
- if (!cp_supportsCheckpoint(result).isOk() || !result)
- return error(ENOTSUP, "Checkpoints not supported");
-
- if (retry < -1) return error(EINVAL, "Retry count must be more than -1");
- std::string content = std::to_string(retry + 1);
- if (retry == -1) {
- android::sp<IBootControl> module = IBootControl::getService();
- if (module) {
- std::string suffix;
- auto cb = [&suffix](hidl_string s) { suffix = s; };
- if (module->getSuffix(module->getCurrentSlot(), cb).isOk()) content += " " + suffix;
- }
- }
- if (!android::base::WriteStringToFile(content, kMetadataCPFile))
- return error("Failed to write checkpoint file");
- return Status::ok();
-}
-
-namespace {
-
-volatile bool isCheckpointing = false;
-
-volatile bool needsCheckpointWasCalled = false;
-
-// Protects isCheckpointing, needsCheckpointWasCalled and code that makes decisions based on status
-// of isCheckpointing
-std::mutex isCheckpointingLock;
-}
-
-Status cp_commitChanges() {
- std::lock_guard<std::mutex> lock(isCheckpointingLock);
-
- if (!isCheckpointing) {
- return Status::ok();
- }
- if (android::base::GetProperty("persist.vold.dont_commit_checkpoint", "0") == "1") {
- LOG(WARNING)
- << "NOT COMMITTING CHECKPOINT BECAUSE persist.vold.dont_commit_checkpoint IS 1";
- return Status::ok();
- }
- // TWRP should not mark errors on slots
- // android::sp<IBootControl> module = IBootControl::getService();
- // if (module) {
- // CommandResult cr;
- // module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
- // if (!cr.success)
- // return error(EINVAL, "Error marking booted successfully: " + std::string(cr.errMsg));
- // LOG(INFO) << "Marked slot as booted successfully.";
- // // Clears the warm reset flag for next reboot.
- // if (!SetProperty("ota.warm_reset", "0")) {
- // LOG(WARNING) << "Failed to reset the warm reset flag";
- // }
- // }
- // Must take action for list of mounted checkpointed things here
- // To do this, we walk the list of mounted file systems.
- // But we also need to get the matching fstab entries to see
- // the original flags
- std::string err_str;
-
- Fstab mounts;
- if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
- return error(EINVAL, "Failed to get /proc/mounts");
- }
-
- // Walk mounted file systems
- for (const auto& mount_rec : mounts) {
- const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
- if (!fstab_rec) continue;
-
- if (fstab_rec->fs_mgr_flags.checkpoint_fs) {
- if (fstab_rec->fs_type == "f2fs") {
- std::string options = mount_rec.fs_options + ",checkpoint=enable";
- if (mount(mount_rec.blk_device.c_str(), mount_rec.mount_point.c_str(), "none",
- MS_REMOUNT | fstab_rec->flags, options.c_str())) {
- return error(EINVAL, "Failed to remount");
- }
- }
- } else if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
- if (!setBowState(mount_rec.blk_device, "2"))
- return error(EINVAL, "Failed to set bow state");
- }
- }
- SetProperty("vold.checkpoint_committed", "1");
- LOG(INFO) << "Checkpoint has been committed.";
- isCheckpointing = false;
- if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
- return error(err_str.c_str());
-
- return Status::ok();
-}
-
-namespace {
-void abort_metadata_file() {
- std::string oldContent, newContent;
- int retry = 0;
- struct stat st;
- int result = stat(kMetadataCPFile.c_str(), &st);
-
- // If the file doesn't exist, we aren't managing a checkpoint retry counter
- if (result != 0) return;
- if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
- PLOG(ERROR) << "Failed to read checkpoint file";
- return;
- }
- std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
-
- if (!android::base::ParseInt(retryContent, &retry)) {
- PLOG(ERROR) << "Could not parse retry count";
- return;
- }
- if (retry > 0) {
- newContent = "0";
- if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
- PLOG(ERROR) << "Could not write checkpoint file";
- }
-}
-} // namespace
-
-void cp_abortChanges(const std::string& message, bool retry) {
- if (!cp_needsCheckpoint()) return;
- if (!retry) abort_metadata_file();
- android_reboot(ANDROID_RB_RESTART2, 0, message.c_str());
-}
-
-bool cp_needsRollback() {
- std::string content;
- bool ret;
-
- ret = android::base::ReadFileToString(kMetadataCPFile, &content);
- if (ret) {
- if (content == "0") return true;
- if (content.substr(0, 3) == "-1 ") {
- std::string oldSuffix = content.substr(3);
- android::sp<IBootControl> module = IBootControl::getService();
- std::string newSuffix;
-
- if (module) {
- auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
- module->getSuffix(module->getCurrentSlot(), cb);
- if (oldSuffix == newSuffix) return true;
- }
- }
- }
- return false;
-}
-
-bool cp_needsCheckpoint() {
- std::lock_guard<std::mutex> lock(isCheckpointingLock);
-
- // Make sure we only return true during boot. See b/138952436 for discussion
- if (needsCheckpointWasCalled) return isCheckpointing;
- needsCheckpointWasCalled = true;
-
- bool ret;
- std::string content;
- android::sp<IBootControl> module = IBootControl::getService();
-
- if (isCheckpointing) return isCheckpointing;
-
- if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
- isCheckpointing = true;
- return true;
- }
- ret = android::base::ReadFileToString(kMetadataCPFile, &content);
- if (ret) {
- ret = content != "0";
- isCheckpointing = ret;
- return ret;
- }
- return false;
-}
-
-bool cp_isCheckpointing() {
- return isCheckpointing;
-}
-
-namespace {
-const std::string kSleepTimeProp = "ro.sys.cp_msleeptime";
-const uint32_t msleeptime_default = 1000; // 1 s
-const uint32_t max_msleeptime = 3600000; // 1 h
-
-const std::string kMinFreeBytesProp = "ro.sys.cp_min_free_bytes";
-const uint64_t min_free_bytes_default = 100 * (1 << 20); // 100 MiB
-
-const std::string kCommitOnFullProp = "ro.sys.cp_commit_on_full";
-const bool commit_on_full_default = true;
-
-static void cp_healthDaemon(std::string mnt_pnt, std::string blk_device, bool is_fs_cp) {
- struct statvfs data;
- uint32_t msleeptime = GetUintProperty(kSleepTimeProp, msleeptime_default, max_msleeptime);
- uint64_t min_free_bytes =
- GetUintProperty(kMinFreeBytesProp, min_free_bytes_default, (uint64_t)-1);
- bool commit_on_full = GetBoolProperty(kCommitOnFullProp, commit_on_full_default);
-
- struct timespec req;
- req.tv_sec = msleeptime / 1000;
- msleeptime %= 1000;
- req.tv_nsec = msleeptime * 1000000;
- while (isCheckpointing) {
- uint64_t free_bytes = 0;
- if (is_fs_cp) {
- statvfs(mnt_pnt.c_str(), &data);
- free_bytes = ((uint64_t) data.f_bavail) * data.f_frsize;
- } else {
- std::string bow_device = fs_mgr_find_bow_device(blk_device);
- if (!bow_device.empty()) {
- std::string content;
- if (android::base::ReadFileToString(bow_device + "/bow/free", &content)) {
- free_bytes = std::strtoull(content.c_str(), NULL, 10);
- }
- }
- }
- if (free_bytes < min_free_bytes) {
- if (commit_on_full) {
- LOG(INFO) << "Low space for checkpointing. Commiting changes";
- cp_commitChanges();
- break;
- } else {
- LOG(INFO) << "Low space for checkpointing. Rebooting";
- cp_abortChanges("checkpoint,low_space", false);
- break;
- }
- }
- nanosleep(&req, NULL);
- }
-}
-
-} // namespace
-
-Status cp_prepareCheckpoint() {
- // Log to notify CTS - see b/137924328 for context
- LOG(INFO) << "cp_prepareCheckpoint called";
- std::lock_guard<std::mutex> lock(isCheckpointingLock);
- if (!isCheckpointing) {
- return Status::ok();
- }
-
- Fstab mounts;
- if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
- return error(EINVAL, "Failed to get /proc/mounts");
- }
-
- for (const auto& mount_rec : mounts) {
- const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
- if (!fstab_rec) continue;
-
- if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
- android::base::unique_fd fd(
- TEMP_FAILURE_RETRY(open(mount_rec.mount_point.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open mount point" << mount_rec.mount_point;
- continue;
- }
-
- struct fstrim_range range = {};
- range.len = ULLONG_MAX;
- nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
- if (ioctl(fd, FITRIM, &range)) {
- PLOG(ERROR) << "Failed to trim " << mount_rec.mount_point;
- continue;
- }
- nsecs_t time = systemTime(SYSTEM_TIME_BOOTTIME) - start;
- LOG(INFO) << "Trimmed " << range.len << " bytes on " << mount_rec.mount_point << " in "
- << nanoseconds_to_milliseconds(time) << "ms for checkpoint";
-
- setBowState(mount_rec.blk_device, "1");
- }
- if (fstab_rec->fs_mgr_flags.checkpoint_blk || fstab_rec->fs_mgr_flags.checkpoint_fs) {
- std::thread(cp_healthDaemon, std::string(mount_rec.mount_point),
- std::string(mount_rec.blk_device),
- fstab_rec->fs_mgr_flags.checkpoint_fs == 1)
- .detach();
- }
- }
- return Status::ok();
-}
-
-namespace {
-const int kSectorSize = 512;
-
-typedef uint64_t sector_t;
-
-struct log_entry {
- sector_t source; // in sectors of size kSectorSize
- sector_t dest; // in sectors of size kSectorSize
- uint32_t size; // in bytes
- uint32_t checksum;
-} __attribute__((packed));
-
-struct log_sector_v1_0 {
- uint32_t magic;
- uint16_t header_version;
- uint16_t header_size;
- uint32_t block_size;
- uint32_t count;
- uint32_t sequence;
- uint64_t sector0;
-} __attribute__((packed));
-
-// MAGIC is BOW in ascii
-const int kMagic = 0x00574f42;
-// Partially restored MAGIC is WOB in ascii
-const int kPartialRestoreMagic = 0x00424f57;
-
-void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
- static uint32_t table[0x100] = {
- 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
- 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
- 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
- 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
- 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
- 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
- 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
- 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
- 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
- 0xB6662D3D,
-
- 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
- 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
- 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
- 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
- 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
- 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
- 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
- 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
- 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
- 0xC0BA6CAD,
-
- 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
- 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
- 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
- 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
- 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
- 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
- 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
- 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
- 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
- 0x5BDEAE1D,
-
- 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
- 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
- 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
- 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
- 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
- 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
- 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
- 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
- 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
- 0x2D02EF8D};
-
- for (size_t i = 0; i < n_bytes; ++i) {
- *crc ^= ((uint8_t*)data)[i];
- *crc = table[(uint8_t)*crc] ^ *crc >> 8;
- }
-}
-
-// A map of relocations.
-// The map must be initialized so that relocations[0] = 0
-// During restore, we replay the log records in reverse, copying from dest to
-// source
-// To validate, we must be able to read the 'dest' sectors as though they had
-// been copied but without actually copying. This map represents how the sectors
-// would have been moved. To read a sector s, find the index <= s and read
-// relocations[index] + s - index
-typedef std::map<sector_t, sector_t> Relocations;
-
-void relocate(Relocations& relocations, sector_t dest, sector_t source, int count) {
- // Find first one we're equal to or greater than
- auto s = --relocations.upper_bound(source);
-
- // Take slice
- Relocations slice;
- slice[dest] = source - s->first + s->second;
- ++s;
-
- // Add rest of elements
- for (; s != relocations.end() && s->first < source + count; ++s)
- slice[dest - source + s->first] = s->second;
-
- // Split range at end of dest
- auto dest_end = --relocations.upper_bound(dest + count);
- relocations[dest + count] = dest + count - dest_end->first + dest_end->second;
-
- // Remove all elements in [dest, dest + count)
- relocations.erase(relocations.lower_bound(dest), relocations.lower_bound(dest + count));
-
- // Add new elements
- relocations.insert(slice.begin(), slice.end());
-}
-
-// A map of sectors that have been written to.
-// The final entry must always be False.
-// When we restart the restore after an interruption, we must take care that
-// when we copy from dest to source, that the block we copy to was not
-// previously copied from.
-// i e. A->B C->A; If we replay this sequence, we end up copying C->B
-// We must save our partial result whenever we finish a page, or when we copy
-// to a location that was copied from earlier (our source is an earlier dest)
-typedef std::map<sector_t, bool> Used_Sectors;
-
-bool checkCollision(Used_Sectors& used_sectors, sector_t start, sector_t end) {
- auto second_overlap = used_sectors.upper_bound(start);
- auto first_overlap = --second_overlap;
-
- if (first_overlap->second) {
- return true;
- } else if (second_overlap != used_sectors.end() && second_overlap->first < end) {
- return true;
- }
- return false;
-}
-
-void markUsed(Used_Sectors& used_sectors, sector_t start, sector_t end) {
- auto start_pos = used_sectors.insert_or_assign(start, true).first;
- auto end_pos = used_sectors.insert_or_assign(end, false).first;
-
- if (start_pos == used_sectors.begin() || !std::prev(start_pos)->second) {
- start_pos++;
- }
- if (std::next(end_pos) != used_sectors.end() && !std::next(end_pos)->second) {
- end_pos++;
- }
- if (start_pos->first < end_pos->first) {
- used_sectors.erase(start_pos, end_pos);
- }
-}
-
-// Restores the given log_entry's data from dest -> source
-// If that entry is a log sector, set the magic to kPartialRestoreMagic and flush.
-void restoreSector(int device_fd, Used_Sectors& used_sectors, std::vector<char>& ls_buffer,
- log_entry* le, std::vector<char>& buffer) {
- log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);
- uint32_t index = le - ((log_entry*)&ls_buffer[ls.header_size]);
- int count = (le->size - 1) / kSectorSize + 1;
-
- if (checkCollision(used_sectors, le->source, le->source + count)) {
- fsync(device_fd);
- lseek64(device_fd, 0, SEEK_SET);
- ls.count = index + 1;
- ls.magic = kPartialRestoreMagic;
- write(device_fd, &ls_buffer[0], ls.block_size);
- fsync(device_fd);
- used_sectors.clear();
- used_sectors[0] = false;
- }
-
- markUsed(used_sectors, le->dest, le->dest + count);
-
- if (index == 0 && ls.sequence != 0) {
- log_sector_v1_0* next = reinterpret_cast<log_sector_v1_0*>(&buffer[0]);
- if (next->magic == kMagic) {
- next->magic = kPartialRestoreMagic;
- }
- }
-
- lseek64(device_fd, le->source * kSectorSize, SEEK_SET);
- write(device_fd, &buffer[0], le->size);
-
- if (index == 0) {
- fsync(device_fd);
- }
-}
-
-// Read from the device
-// If we are validating, the read occurs as though the relocations had happened
-std::vector<char> relocatedRead(int device_fd, Relocations const& relocations, bool validating,
- sector_t sector, uint32_t size, uint32_t block_size) {
- if (!validating) {
- std::vector<char> buffer(size);
- lseek64(device_fd, sector * kSectorSize, SEEK_SET);
- read(device_fd, &buffer[0], size);
- return buffer;
- }
-
- std::vector<char> buffer(size);
- for (uint32_t i = 0; i < size; i += block_size, sector += block_size / kSectorSize) {
- auto relocation = --relocations.upper_bound(sector);
- lseek64(device_fd, (sector + relocation->second - relocation->first) * kSectorSize,
- SEEK_SET);
- read(device_fd, &buffer[i], block_size);
- }
-
- return buffer;
-}
-
-} // namespace
-
-Status cp_restoreCheckpoint(const std::string& blockDevice, int restore_limit) {
- bool validating = true;
- std::string action = "Validating";
- int restore_count = 0;
-
- for (;;) {
- Relocations relocations;
- relocations[0] = 0;
- Status status = Status::ok();
-
- LOG(INFO) << action << " checkpoint on " << blockDevice;
- android::base::unique_fd device_fd(open(blockDevice.c_str(), O_RDWR | O_CLOEXEC));
- if (device_fd < 0) return error("Cannot open " + blockDevice);
-
- log_sector_v1_0 original_ls;
- read(device_fd, reinterpret_cast<char*>(&original_ls), sizeof(original_ls));
- if (original_ls.magic == kPartialRestoreMagic) {
- validating = false;
- action = "Restoring";
- } else if (original_ls.magic != kMagic) {
- return error(EINVAL, "No magic");
- }
-
- LOG(INFO) << action << " " << original_ls.sequence << " log sectors";
-
- for (int sequence = original_ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
- auto ls_buffer = relocatedRead(device_fd, relocations, validating, 0,
- original_ls.block_size, original_ls.block_size);
- log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);
-
- Used_Sectors used_sectors;
- used_sectors[0] = false;
-
- if (ls.magic != kMagic && (ls.magic != kPartialRestoreMagic || validating)) {
- status = error(EINVAL, "No magic");
- break;
- }
-
- if (ls.block_size != original_ls.block_size) {
- status = error(EINVAL, "Block size mismatch");
- break;
- }
-
- if ((int)ls.sequence != sequence) {
- status = error(EINVAL, "Expecting log sector " + std::to_string(sequence) +
- " but got " + std::to_string(ls.sequence));
- break;
- }
-
- LOG(INFO) << action << " from log sector " << ls.sequence;
- for (log_entry* le =
- reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]) + ls.count - 1;
- le >= reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]); --le) {
- // This is very noisy - limit to DEBUG only
- LOG(VERBOSE) << action << " " << le->size << " bytes from sector " << le->dest
- << " to " << le->source << " with checksum " << std::hex
- << le->checksum;
-
- auto buffer = relocatedRead(device_fd, relocations, validating, le->dest, le->size,
- ls.block_size);
- uint32_t checksum = le->source / (ls.block_size / kSectorSize);
- for (size_t i = 0; i < le->size; i += ls.block_size) {
- crc32(&buffer[i], ls.block_size, &checksum);
- }
-
- if (le->checksum && checksum != le->checksum) {
- status = error(EINVAL, "Checksums don't match");
- break;
- }
-
- if (validating) {
- relocate(relocations, le->source, le->dest, (le->size - 1) / kSectorSize + 1);
- } else {
- restoreSector(device_fd, used_sectors, ls_buffer, le, buffer);
- restore_count++;
- if (restore_limit && restore_count >= restore_limit) {
- status = error(EAGAIN, "Hit the test limit");
- break;
- }
- }
- }
- }
-
- if (!status.isOk()) {
- if (!validating) {
- LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
- return status;
- }
-
- LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
- auto buffer = relocatedRead(device_fd, relocations, false, original_ls.sector0,
- original_ls.block_size, original_ls.block_size);
- lseek64(device_fd, 0, SEEK_SET);
- write(device_fd, &buffer[0], original_ls.block_size);
- return Status::ok();
- }
-
- if (!validating) break;
-
- validating = false;
- action = "Restoring";
- }
-
- return Status::ok();
-}
-
-Status cp_markBootAttempt() {
- std::string oldContent, newContent;
- int retry = 0;
- struct stat st;
- int result = stat(kMetadataCPFile.c_str(), &st);
-
- // If the file doesn't exist, we aren't managing a checkpoint retry counter
- if (result != 0) return Status::ok();
- if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent))
- return error("Failed to read checkpoint file");
- std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
-
- if (!android::base::ParseInt(retryContent, &retry))
- return error(EINVAL, "Could not parse retry count");
- if (retry > 0) {
- retry--;
-
- newContent = std::to_string(retry);
- if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
- return error("Could not write checkpoint file");
- }
- return Status::ok();
-}
-
-void cp_resetCheckpoint() {
- std::lock_guard<std::mutex> lock(isCheckpointingLock);
- needsCheckpointWasCalled = false;
-}
diff --git a/crypto/fscrypt/Checkpoint.h b/crypto/fscrypt/Checkpoint.h
deleted file mode 100644
index cd17c78..0000000
--- a/crypto/fscrypt/Checkpoint.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2018 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 _CHECKPOINT_H
-#define _CHECKPOINT_H
-
-#include <binder/Status.h>
-#include <string>
-
-
-android::binder::Status cp_supportsCheckpoint(bool& result);
-
-android::binder::Status cp_supportsBlockCheckpoint(bool& result);
-
-android::binder::Status cp_supportsFileCheckpoint(bool& result);
-
-android::binder::Status cp_startCheckpoint(int retry);
-
-android::binder::Status cp_commitChanges();
-
-void cp_abortChanges(const std::string& message, bool retry);
-
-bool cp_needsRollback();
-
-bool cp_needsCheckpoint();
-
-bool cp_isCheckpointing();
-
-android::binder::Status cp_prepareCheckpoint();
-
-android::binder::Status cp_restoreCheckpoint(const std::string& mountPoint, int count = 0);
-
-android::binder::Status cp_markBootAttempt();
-
-void cp_resetCheckpoint();
-
-#endif
diff --git a/crypto/fscrypt/CryptoType.cpp b/crypto/fscrypt/CryptoType.cpp
deleted file mode 100644
index cf1ef42..0000000
--- a/crypto/fscrypt/CryptoType.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 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 "CryptoType.h"
-
-#include <string.h>
-
-#include <android-base/logging.h>
-#include <cutils/properties.h>
-
-
-const CryptoType& lookup_crypto_algorithm(const CryptoType table[], int table_len,
- const CryptoType& default_alg, const char* property) {
- char paramstr[PROPERTY_VALUE_MAX];
-
- property_get(property, paramstr, default_alg.get_config_name());
- for (int i = 0; i < table_len; i++) {
- if (strcmp(paramstr, table[i].get_config_name()) == 0) {
- return table[i];
- }
- }
- LOG(ERROR) << "Invalid name (" << paramstr << ") for " << property << ". Defaulting to "
- << default_alg.get_config_name() << ".";
- return default_alg;
-}
diff --git a/crypto/fscrypt/CryptoType.h b/crypto/fscrypt/CryptoType.h
deleted file mode 100644
index 79ea93d..0000000
--- a/crypto/fscrypt/CryptoType.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#pragma once
-
-#include <stdlib.h>
-
-
-// Struct representing an encryption algorithm supported by vold.
-// "config_name" represents the name we give the algorithm in
-// read-only properties and fstab files
-// "kernel_name" is the name we present to the Linux kernel
-// "keysize" is the size of the key in bytes.
-struct CryptoType {
- // We should only be constructing CryptoTypes as part of
- // supported_crypto_types[]. We do it via this pseudo-builder pattern,
- // which isn't pure or fully protected as a concession to being able to
- // do it all at compile time. Add new CryptoTypes in
- // supported_crypto_types[] below.
- constexpr CryptoType() : CryptoType(nullptr, nullptr, 0xFFFFFFFF) {}
- constexpr CryptoType set_keysize(size_t size) const {
- return CryptoType(this->config_name, this->kernel_name, size);
- }
- constexpr CryptoType set_config_name(const char* property) const {
- return CryptoType(property, this->kernel_name, this->keysize);
- }
- constexpr CryptoType set_kernel_name(const char* crypto) const {
- return CryptoType(this->config_name, crypto, this->keysize);
- }
-
- constexpr const char* get_config_name() const { return config_name; }
- constexpr const char* get_kernel_name() const { return kernel_name; }
- constexpr size_t get_keysize() const { return keysize; }
-
- private:
- const char* config_name;
- const char* kernel_name;
- size_t keysize;
-
- constexpr CryptoType(const char* property, const char* crypto, size_t ksize)
- : config_name(property), kernel_name(crypto), keysize(ksize) {}
-};
-
-// Use the named android property to look up a type from the table
-// If the property is not set or matches no table entry, return the default.
-const CryptoType& lookup_crypto_algorithm(const CryptoType table[], int table_len,
- const CryptoType& default_alg, const char* property);
-
-// Some useful types
-
-constexpr CryptoType invalid_crypto_type = CryptoType();
-
-constexpr CryptoType aes_256_xts = CryptoType()
- .set_config_name("aes-256-xts")
- .set_kernel_name("aes-xts-plain64")
- .set_keysize(64);
-
-constexpr CryptoType adiantum = CryptoType()
- .set_config_name("adiantum")
- .set_kernel_name("xchacha12,aes-adiantum-plain64")
- .set_keysize(32);
-
-// Support compile-time validation of a crypto type table
-
-template <typename T, size_t N>
-constexpr size_t array_length(T (&)[N]) {
- return N;
-}
-
-constexpr bool isValidCryptoType(size_t max_keylen, const CryptoType& crypto_type) {
- return ((crypto_type.get_config_name() != nullptr) &&
- (crypto_type.get_kernel_name() != nullptr) &&
- (crypto_type.get_keysize() <= max_keylen));
-}
-
-// Confirms that all supported_crypto_types have a small enough keysize and
-// had both set_config_name() and set_kernel_name() called.
-// Note in C++11 that constexpr functions can only have a single line.
-// So our code is a bit convoluted (using recursion instead of a loop),
-// but it's asserting at compile time that all of our key lengths are valid.
-constexpr bool validateSupportedCryptoTypes(size_t max_keylen, const CryptoType types[],
- size_t len) {
- return len == 0 || (isValidCryptoType(max_keylen, types[len - 1]) &&
- validateSupportedCryptoTypes(max_keylen, types, len - 1));
-}
diff --git a/crypto/fscrypt/Decrypt.cpp b/crypto/fscrypt/Decrypt.cpp
deleted file mode 100755
index 0217358..0000000
--- a/crypto/fscrypt/Decrypt.cpp
+++ /dev/null
@@ -1,1220 +0,0 @@
-/*
- * Copyright (C) 2016 - 2020 The TeamWin Recovery 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 "Decrypt.h"
-#include "FsCrypt.h"
-#include <fscrypt/fscrypt.h>
-
-#include <map>
-#include <string>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#ifndef HAVE_LIBKEYUTILS
-#include "key_control.h"
-#else
-#include <keyutils.h>
-#endif
-#include "keystore_client.pb.h"
-#include "Weaver1.h"
-#include "cutils/properties.h"
-
-#include <openssl/sha.h>
-#include <openssl/aes.h>
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-
-#include <dirent.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/types.h>
-#include <fstream>
-#include <future>
-#include <algorithm>
-
-#include <android-base/file.h>
-#include <base/threading/platform_thread.h>
-#include <android/hardware/confirmationui/1.0/types.h>
-#include <android/security/BnConfirmationPromptCallback.h>
-#include <android/security/keystore/IKeystoreService.h>
-#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
-
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <hardware/hw_auth_token.h>
-
-#include <keystore/keystore.h>
-#include <keystore/keystore_client.h>
-#include <keystore/keystore_client_impl.h>
-#include <keystore/KeystoreResponse.h>
-#include <keystore/keystore_hidl_support.h>
-#include <keystore/keystore_promises.h>
-#include <keystore/keystore_return_types.h>
-#include <keystore/keymaster_types.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <keystore/OperationResult.h>
-#include "keystore_client.pb.h"
-
-#include <keymasterV4_1/authorization_set.h>
-#include <keymasterV4_1/keymaster_utils.h>
-
-extern "C" {
-#include "crypto_scrypt.h"
-}
-
-#include "fscrypt_policy.h"
-#include "fscrypt-common.h"
-#include "HashPassword.h"
-#include "KeyStorage.h"
-#include "android/os/IVold.h"
-
-using android::security::keystore::IKeystoreService;
-using keystore::KeystoreResponsePromise;
-using keystore::OperationResultPromise;
-using android::security::keymaster::OperationResult;
-using android::hardware::keymaster::V4_1::support::blob2hidlVec;
-
-
-inline std::string hidlVec2String(const ::keystore::hidl_vec<uint8_t>& value) {
- return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size());
-}
-
-static bool lookup_ref_key_internal(std::map<userid_t, android::fscrypt::EncryptionPolicy> key_map, const uint8_t* policy, userid_t* user_id) {
-#ifdef USE_FSCRYPT_POLICY_V1
- char policy_string_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
- char key_map_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
- bytes_to_hex(policy, FS_KEY_DESCRIPTOR_SIZE, policy_string_hex);
-#else
- char policy_string_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
- char key_map_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
- bytes_to_hex(policy, FSCRYPT_KEY_IDENTIFIER_SIZE, policy_string_hex);
-#endif
-
- for (std::map<userid_t, android::fscrypt::EncryptionPolicy>::iterator it=key_map.begin(); it!=key_map.end(); ++it) {
-#ifdef USE_FSCRYPT_POLICY_V1
- bytes_to_hex(reinterpret_cast<const uint8_t*>(&it->second.key_raw_ref[0]), FS_KEY_DESCRIPTOR_SIZE, key_map_hex);
-#else
- bytes_to_hex(reinterpret_cast<const uint8_t*>(&it->second.key_raw_ref[0]), FSCRYPT_KEY_IDENTIFIER_SIZE, key_map_hex);
-#endif
- std::string key_map_hex_string = std::string(key_map_hex);
- if (key_map_hex_string == policy_string_hex) {
- *user_id = it->first;
- return true;
- }
- }
- return false;
-}
-
-#ifdef USE_FSCRYPT_POLICY_V1
-extern "C" bool lookup_ref_key(fscrypt_policy_v1* fep, uint8_t* policy_type) {
-#else
-extern "C" bool lookup_ref_key(fscrypt_policy_v2* fep, uint8_t* policy_type) {
-#endif
- userid_t user_id = 0;
- std::string policy_type_string;
-
-#ifdef USE_FSCRYPT_POLICY_V1
- char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
- bytes_to_hex(fep->master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE, policy_hex);
- if (std::strncmp((const char*)fep->master_key_descriptor, de_key_raw_ref.c_str(), FS_KEY_DESCRIPTOR_SIZE) == 0) {
- policy_type_string = SYSTEM_DE_FSCRYPT_POLICY;
- memcpy(policy_type, policy_type_string.data(), policy_type_string.size());
- return true;
- }
- if (!lookup_ref_key_internal(s_de_policies, fep->master_key_descriptor, &user_id)) {
- if (!lookup_ref_key_internal(s_ce_policies, fep->master_key_descriptor, &user_id)) {
- return false;
- } else {
- policy_type_string = USER_CE_FSCRYPT_POLICY + std::to_string(user_id);
- }
- } else {
- policy_type_string = USER_DE_FSCRYPT_POLICY + std::to_string(user_id);
- }
-#else
- char policy_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
- bytes_to_hex(fep->master_key_identifier, FSCRYPT_KEY_IDENTIFIER_SIZE, policy_hex);
- if (std::strncmp((const char*)fep->master_key_identifier, de_key_raw_ref.c_str(), FSCRYPT_KEY_IDENTIFIER_SIZE) == 0) {
- policy_type_string = SYSTEM_DE_FSCRYPT_POLICY;
- memcpy(policy_type, policy_type_string.data(), policy_type_string.size());
- return true;
- }
- if (!lookup_ref_key_internal(s_de_policies, fep->master_key_identifier, &user_id)) {
- if (!lookup_ref_key_internal(s_ce_policies, fep->master_key_identifier, &user_id)) {
- return false;
- } else {
- policy_type_string = USER_CE_FSCRYPT_POLICY + std::to_string(user_id);
- }
- } else {
- policy_type_string = USER_DE_FSCRYPT_POLICY + std::to_string(user_id);
- }
-#endif
-
- memcpy(policy_type, policy_type_string.data(), policy_type_string.size());
- LOG(INFO) << "storing policy type: " << policy_type;
- return true;
-}
-
-extern "C" bool lookup_ref_tar(const uint8_t* policy_type, uint8_t* policy) {
- std::string policy_type_string = std::string((char *) policy_type);
-#ifdef USE_FSCRYPT_POLICY_V1
- char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
- bytes_to_hex(policy_type, FS_KEY_DESCRIPTOR_SIZE, policy_hex);
-#else
- char policy_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
- bytes_to_hex(policy_type, FSCRYPT_KEY_IDENTIFIER_SIZE, policy_hex);
-#endif
-
- userid_t user_id = atoi(policy_type_string.substr(3, 4).c_str());
-
- // TODO Update version # and make magic strings
-#ifdef USE_FSCRYPT_POLICY_V1
- if (policy_type_string.substr(0,1) != FSCRYPT_V1) {
-#else
- if (policy_type_string.substr(0,1) != FSCRYPT_V2) {
-#endif
- LOG(ERROR) << "Unexpected version:" << policy_type[0];
- return false;
- }
-
- if (policy_type_string.substr(1, 2) == SYSTEM_DE_KEY) {
- memcpy(policy, de_key_raw_ref.data(), de_key_raw_ref.size());
- return true;
- }
-
- std::string raw_ref;
-
- if (policy_type_string.substr(1, 1) == USER_DE_KEY) {
- if (lookup_key_ref(s_de_policies, user_id, &raw_ref)) {
- memcpy(policy, raw_ref.data(), raw_ref.size());
- } else
- return false;
- } else if (policy_type_string.substr(1, 1) == USER_CE_KEY) {
- if (lookup_key_ref(s_ce_policies, user_id, &raw_ref)) {
- memcpy(policy, raw_ref.data(), raw_ref.size());
- } else
- return false;
- } else {
- LOG(ERROR) << "unknown policy type: " << policy_type;
- return false;
- }
- return true;
-}
-
-bool Decrypt_DE() {
- if (!fscrypt_initialize_systemwide_keys()) { // this deals with the overarching device encryption
- printf("fscrypt_initialize_systemwide_keys returned fail\n");
- return false;
- }
- if (!fscrypt_init_user0()) {
- printf("fscrypt_init_user0 returned fail\n");
- return false;
- }
- return true;
-}
-
-// Crappy functions for debugging, please ignore unless you need to debug
-// void output_hex(const std::string& in) {
-// const char *buf = in.data();
-// char hex[in.size() * 2 + 1];
-// unsigned int index;
-// for (index = 0; index < in.size(); index++)
-// sprintf(&hex[2 * index], "%02X", buf[index]);
-// printf("%s", hex);
-// }
-
-// void output_hex(const char* buf, const int size) {
-// char hex[size * 2 + 1];
-// int index;
-// for (index = 0; index < size; index++)
-// sprintf(&hex[2 * index], "%02X", buf[index]);
-// printf("%s", hex);
-// }
-
-// void output_hex(const unsigned char* buf, const int size) {
-// char hex[size * 2 + 1];
-// int index;
-// for (index = 0; index < size; index++)
-// sprintf(&hex[2 * index], "%02X", buf[index]);
-// printf("%s", hex);
-// }
-
-// void output_hex(std::vector<uint8_t>* vec) {
-// char hex[3];
-// unsigned int index;
-// for (index = 0; index < vec->size(); index++) {
-// sprintf(&hex[0], "%02X", vec->at(index));
-// printf("%s", hex);
-// }
-// }
-
-/* An alternative is to use:
- * sqlite3 /data/system/locksettings.db "SELECT value FROM locksettings WHERE name='sp-handle' AND user=0;"
- * but we really don't want to include the 1.1MB libsqlite in TWRP. We scan the spblob folder for the
- * password data file (*.pwd) and get the handle from the filename instead. This is a replacement for
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/LockSettingsService.java#2017
- * We never use this data as an actual long. We always use it as a string. */
-bool Find_Handle(const std::string& spblob_path, std::string& handle_str) {
- DIR* dir = opendir(spblob_path.c_str());
- if (!dir) {
- printf("Error opening '%s'\n", spblob_path.c_str());
- return false;
- }
-
- struct dirent* de = 0;
-
- while ((de = readdir(dir)) != 0) {
- if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
- continue;
- size_t len = strlen(de->d_name);
- if (len <= 4)
- continue;
- char* p = de->d_name;
- p += len - 4;
- if (strncmp(p, ".pwd", 4) == 0) {
- handle_str = de->d_name;
- handle_str = handle_str.substr(0, len - 4);
- //*handle = strtoull(handle_str.c_str(), 0 , 16);
- closedir(dir);
- return true;
- }
- }
- closedir(dir);
- return false;
-}
-
-/* This is the structure of the data in the password data (*.pwd) file which the structure can be found
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#187 */
-struct password_data_struct {
- int password_type;
- unsigned char scryptN;
- unsigned char scryptR;
- unsigned char scryptP;
- int salt_len;
- void* salt;
- int handle_len;
- void* password_handle;
-};
-
-/* C++ replacement for
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#764 */
-bool Get_Password_Data(const std::string& spblob_path, const std::string& handle_str, password_data_struct *pwd) {
- std::string pwd_file = spblob_path + handle_str + ".pwd";
- std::string pwd_data;
- if (!android::base::ReadFileToString(pwd_file, &pwd_data)) {
- printf("Failed to read '%s'\n", pwd_file.c_str());
- return false;
- }
- // output_hex(pwd_data.data(), pwd_data.size());printf("\n");
- const int* intptr = (const int*)pwd_data.data();
- pwd->password_type = *intptr;
- endianswap(&pwd->password_type);
- //printf("password type %i\n", pwd->password_type); // 2 was PIN, 1 for pattern, 2 also for password, -1 for default password
- const unsigned char* byteptr = (const unsigned char*)pwd_data.data() + sizeof(int);
- pwd->scryptN = *byteptr;
- byteptr++;
- pwd->scryptR = *byteptr;
- byteptr++;
- pwd->scryptP = *byteptr;
- byteptr++;
- intptr = (const int*)byteptr;
- pwd->salt_len = *intptr;
- endianswap(&pwd->salt_len);
- if (pwd->salt_len != 0) {
- pwd->salt = malloc(pwd->salt_len);
- if (!pwd->salt) {
- printf("Get_Password_Data malloc salt\n");
- return false;
- }
- memcpy(pwd->salt, intptr + 1, pwd->salt_len);
- intptr++;
- byteptr = (const unsigned char*)intptr;
- byteptr += pwd->salt_len;
- } else {
- printf("Get_Password_Data salt_len is 0\n");
- return false;
- }
- intptr = (const int*)byteptr;
- pwd->handle_len = *intptr;
- endianswap(&pwd->handle_len);
- if (pwd->handle_len != 0) {
- pwd->password_handle = malloc(pwd->handle_len);
- if (!pwd->password_handle) {
- printf("Get_Password_Data malloc password_handle\n");
- return false;
- }
- memcpy(pwd->password_handle, intptr + 1, pwd->handle_len);
- } else {
- printf("Get_Password_Data handle_len is 0\n");
- // Not an error if using weaver
- }
- return true;
-}
-
-/* C++ replacement for
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#765
- * called here
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#1050 */
-bool Get_Password_Token(const password_data_struct *pwd, const std::string& Password, unsigned char* password_token) {
- if (!password_token) {
- printf("password_token is null\n");
- return false;
- }
- unsigned int N = 1 << pwd->scryptN;
- unsigned int r = 1 << pwd->scryptR;
- unsigned int p = 1 << pwd->scryptP;
- //printf("N %i r %i p %i\n", N, r, p);
- int ret = crypto_scrypt(reinterpret_cast<const uint8_t*>(Password.data()), Password.size(),
- reinterpret_cast<const uint8_t*>(pwd->salt), pwd->salt_len,
- N, r, p,
- password_token, 32);
- if (ret != 0) {
- printf("scrypt error\n");
- return false;
- }
- return true;
-}
-
-// Data structure for the *.weaver file, see Get_Weaver_Data below
-struct weaver_data_struct {
- unsigned char version;
- int slot;
-};
-
-/* C++ replacement for
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#501
- * called here
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#768 */
-bool Get_Weaver_Data(const std::string& spblob_path, const std::string& handle_str, weaver_data_struct *wd) {
- std::string weaver_file = spblob_path + handle_str + ".weaver";
- std::string weaver_data;
- if (!android::base::ReadFileToString(weaver_file, &weaver_data)) {
- printf("Failed to read '%s'\n", weaver_file.c_str());
- return false;
- }
- // output_hex(weaver_data.data(), weaver_data.size());printf("\n");
- const unsigned char* byteptr = (const unsigned char*)weaver_data.data();
- wd->version = *byteptr;
- // printf("weaver version %i\n", wd->version);
- const int* intptr = (const int*)weaver_data.data() + sizeof(unsigned char);
- wd->slot = *intptr;
- //endianswap(&wd->slot); not needed
- // printf("weaver slot %i\n", wd->slot);
- return true;
-}
-
-namespace android {
-
-// On Android 8.0 for some reason init can't seem to completely stop keystore
-// so we have to kill it too if it doesn't die on its own.
-static void kill_keystore() {
- DIR* dir = opendir("/proc");
- if (dir) {
- struct dirent* de = 0;
-
- while ((de = readdir(dir)) != 0) {
- if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
- continue;
-
- int pid = -1;
- int ret = sscanf(de->d_name, "%d", &pid);
-
- if (ret == 1) {
- char cmdpath[PATH_MAX];
- sprintf(cmdpath, "/proc/%d/cmdline", pid);
-
- FILE* file = fopen(cmdpath, "r");
- size_t task_size = PATH_MAX;
- char task[PATH_MAX];
- char* p = task;
- if (getline(&p, &task_size, file) > 0) {
- if (strstr(task, "keystore") != 0) {
- printf("keystore pid %d found, sending kill.\n", pid);
- kill(pid, SIGINT);
- usleep(5000);
- kill(pid, SIGKILL);
- }
- }
- fclose(file);
- }
- }
- closedir(dir);
- }
-}
-
-// The keystore holds a file open on /data so we have to stop / kill it
-// if we want to be able to unmount /data for things like formatting.
-static void stop_keystore() {
- printf("Stopping keystore...\n");
- property_set("ctl.stop", "keystore");
- usleep(5000);
- kill_keystore();
-}
-
-/* These next 2 functions try to get the keystore service 50 times because
- * the keystore is not always ready when TWRP boots */
-android::sp<IBinder> getKeystoreBinder() {
- android::sp<IServiceManager> sm = android::defaultServiceManager();
- return sm->getService(String16("android.security.keystore"));
-}
-
-android::sp<IBinder> getKeystoreBinderRetry() {
- printf("Starting keystore...\n");
- property_set("ctl.start", "keystore");
- int retry_count = 50;
- android::sp<IBinder> binder = getKeystoreBinder();
- while (binder == NULL && retry_count) {
- printf("Waiting for keystore service... %i\n", retry_count--);
- sleep(1);
- binder = getKeystoreBinder();
- }
- return binder;
-}
-
-namespace keystore {
-
-#define SYNTHETIC_PASSWORD_VERSION_V1 1
-#define SYNTHETIC_PASSWORD_VERSION_V2 2
-#define SYNTHETIC_PASSWORD_VERSION_V3 3
-#define SYNTHETIC_PASSWORD_PASSWORD_BASED 0
-#define SYNTHETIC_PASSWORD_KEY_PREFIX "USRSKEY_synthetic_password_"
-#define USR_PRIVATE_KEY_PREFIX "USRPKEY_synthetic_password_"
-
-static std::string mKey_Prefix;
-
-/* The keystore alias subid is sometimes the same as the handle, but not always.
- * In the case of handle 0c5303fd2010fe29, the alias subid used c5303fd2010fe29
- * without the leading 0. We could try to parse the data from a previous
- * keystore request, but I think this is an easier solution because there
- * is little to no documentation on the format of data we get back from
- * the keystore in this instance. We also want to copy everything to a temp
- * folder so that any key upgrades that might take place do not actually
- * upgrade the keys on the data partition. We rename all 1000 uid files to 0
- * to pass the keystore permission checks. */
-bool Find_Keystore_Alias_SubID_And_Prep_Files(const userid_t user_id, std::string& keystoreid, const std::string& handle_str) {
- char path_c[PATH_MAX];
- sprintf(path_c, "/data/misc/keystore/user_%d", user_id);
- char user_dir[PATH_MAX];
- sprintf(user_dir, "user_%d", user_id);
- std::string source_path = "/data/misc/keystore/";
- source_path += user_dir;
- std::string handle_sub = handle_str;
- while (handle_sub.substr(0,1) == "0") {
- std::string temp = handle_sub.substr(1);
- handle_sub = temp;
- }
- mKey_Prefix = "";
-
- mkdir("/tmp/misc", 0755);
- mkdir("/tmp/misc/keystore", 0755);
- std::string destination_path = "/tmp/misc/keystore/";
- destination_path += user_dir;
- if (mkdir(destination_path.c_str(), 0755) && errno != EEXIST) {
- printf("failed to mkdir '%s' %s\n", destination_path.c_str(), strerror(errno));
- return false;
- }
- destination_path += "/";
-
- DIR* dir = opendir(source_path.c_str());
- if (!dir) {
- printf("Error opening '%s'\n", source_path.c_str());
- return false;
- }
- source_path += "/";
-
- struct dirent* de = 0;
- size_t prefix_len = strlen(SYNTHETIC_PASSWORD_KEY_PREFIX);
- bool found_subid = false;
- bool has_pkey = false; // PKEY has priority over SKEY
-
- while ((de = readdir(dir)) != 0) {
- if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
- continue;
- if (!found_subid) {
- size_t len = strlen(de->d_name);
- if (len <= prefix_len)
- continue;
- if (strstr(de->d_name, SYNTHETIC_PASSWORD_KEY_PREFIX) && !has_pkey)
- mKey_Prefix = SYNTHETIC_PASSWORD_KEY_PREFIX;
- else if (strstr(de->d_name, USR_PRIVATE_KEY_PREFIX)) {
- mKey_Prefix = USR_PRIVATE_KEY_PREFIX;
- has_pkey = true;
- } else
- continue;
- if (strstr(de->d_name, handle_sub.c_str())) {
- keystoreid = handle_sub;
- printf("keystoreid matched handle_sub: '%s'\n", keystoreid.c_str());
- found_subid = true;
- } else {
- std::string file = de->d_name;
- std::size_t found = file.find_last_of("_");
- if (found != std::string::npos) {
- keystoreid = file.substr(found + 1);
- // printf("possible keystoreid: '%s'\n", keystoreid.c_str());
- //found_subid = true; // we'll keep going in hopes that we find a pkey or a match to the handle_sub
- }
- }
- }
- std::string src = source_path;
- src += de->d_name;
- std::ifstream srcif(src.c_str(), std::ios::binary);
- std::string dst = destination_path;
- dst += de->d_name;
- std::size_t source_uid = dst.find("1000");
- if (source_uid != std::string::npos)
- dst.replace(source_uid, 4, "0");
- std::ofstream dstof(dst.c_str(), std::ios::binary);
- printf("copying '%s' to '%s'\n", src.c_str(), dst.c_str());
- dstof << srcif.rdbuf();
- srcif.close();
- dstof.close();
- }
- closedir(dir);
- if (!found_subid && !mKey_Prefix.empty() && !keystoreid.empty())
- found_subid = true;
- return found_subid;
-}
-
-/* C++ replacement for function of the same name
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#867
- * returning an empty string indicates an error */
-std::string unwrapSyntheticPasswordBlob(const std::string& spblob_path, const std::string& handle_str, const userid_t user_id,
- const void* application_id, const size_t application_id_size, uint32_t auth_token_len) {
- std::string disk_decryption_secret_key = "";
-
- android::ProcessState::self()->startThreadPool();
-
- std::string keystore_alias_subid;
- // Can be stored in user 0, so check for both.
- if (!Find_Keystore_Alias_SubID_And_Prep_Files(user_id, keystore_alias_subid, handle_str) &&
- !Find_Keystore_Alias_SubID_And_Prep_Files(0, keystore_alias_subid, handle_str))
- {
- printf("failed to scan keystore alias subid and prep keystore files\n");
- return disk_decryption_secret_key;
- }
-
- // First get the keystore service
- android::sp<IBinder> binder = getKeystoreBinderRetry();
- android::sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
-
- if (service == NULL) {
- printf("error: could not connect to keystore service\n");
- return disk_decryption_secret_key;
- }
-
- if (auth_token_len > 0) {
- printf("Starting keystore_auth service...\n");
- property_set("ctl.start", "keystore_auth");
- }
-
- // Read the data from the .spblob file per: https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#869
- std::string spblob_file = spblob_path + handle_str + ".spblob";
- std::string spblob_data;
- if (!android::base::ReadFileToString(spblob_file, &spblob_data)) {
- printf("Failed to read '%s'\n", spblob_file.c_str());
- return disk_decryption_secret_key;
- }
- unsigned char* byteptr = (unsigned char*)spblob_data.data();
- if (*byteptr != SYNTHETIC_PASSWORD_VERSION_V2 && *byteptr != SYNTHETIC_PASSWORD_VERSION_V1
- && *byteptr != SYNTHETIC_PASSWORD_VERSION_V3) {
- printf("Unsupported synthetic password version %i\n", *byteptr);
- return disk_decryption_secret_key;
- }
- const unsigned char* synthetic_password_version = byteptr;
- byteptr++;
- if (*byteptr != SYNTHETIC_PASSWORD_PASSWORD_BASED) {
- printf("spblob data is not SYNTHETIC_PASSWORD_PASSWORD_BASED\n");
- return disk_decryption_secret_key;
- }
- byteptr++; // Now we're pointing to the blob data itself
- if (*synthetic_password_version == SYNTHETIC_PASSWORD_VERSION_V2
- || *synthetic_password_version == SYNTHETIC_PASSWORD_VERSION_V3) {
- printf("spblob v2 / v3\n");
- /* Version 2 / 3 of the spblob is basically the same as version 1, but the order of getting the intermediate key and disk decryption key have been flip-flopped
- * as seen in https://android.googlesource.com/platform/frameworks/base/+/5025791ac6d1538224e19189397de8d71dcb1a12
- */
- /* First decrypt call found in
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java#135
- * We will use https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
- * and https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
- * First we set some algorithm parameters as seen in two places:
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java#297
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java#216 */
- // When using secdis (aka not weaver) you must supply an auth token to the keystore prior to the begin operation
- if (auth_token_len > 0) {
- /*::keystore::KeyStoreServiceReturnCode auth_result = service->addAuthToken(auth_token, auth_token_len);
- if (!auth_result.isOk()) {
- // The keystore checks the uid of the calling process and will return a permission denied on this operation for user 0
- printf("keystore error adding auth token\n");
- return disk_decryption_secret_key;
- }*/
- // The keystore refuses to allow the root user to supply auth tokens, so we write the auth token to a file earlier and
- // run a separate service that runs user the system user to add the auth token. We wait for the auth token file to be
- // deleted by the keymaster_auth service and check for a /auth_error file in case of errors. We quit after after a while if
- // the /auth_token file never gets deleted.
- int auth_wait_count = 20;
- while (access("/auth_token", F_OK) == 0 && auth_wait_count-- > 0)
- usleep(5000);
- if (auth_wait_count == 0 || access("/auth_error", F_OK) == 0) {
- printf("error during keymaster_auth service\n");
- /* If you are getting this error, make sure that you have the keymaster_auth service defined in your init scripts, preferrably in init.recovery.{ro.hardware}.rc
- * service keystore_auth /system/bin/keystore_auth
- * disabled
- * oneshot
- * user system
- * group root
- * seclabel u:r:recovery:s0
- *
- * And check dmesg for error codes regarding this service if needed. */
- return disk_decryption_secret_key;
- }
- }
- int32_t ret;
- size_t maclen = 128;
- unsigned char* iv = (unsigned char*)byteptr; // The IV is the first 12 bytes of the spblob
- ::keystore::hidl_vec<uint8_t> iv_hidlvec;
- iv_hidlvec.setToExternal((unsigned char*)byteptr, 12);
- // printf("iv: "); output_hex((const unsigned char*)iv, 12); printf("\n");
- std::string keystore_alias = mKey_Prefix;
- keystore_alias += keystore_alias_subid;
- String16 keystore_alias16(keystore_alias.data(), keystore_alias.size());
- int32_t error_code;
- unsigned char* cipher_text = (unsigned char*)byteptr + 12; // The cipher text comes immediately after the IV
- std::string cipher_text_str(byteptr, byteptr + spblob_data.size() - 14);
-
- ::keystore::hidl_vec<uint8_t> cipher_text_hidlvec;
- ::keystore::AuthorizationSetBuilder begin_params;
-
- cipher_text_hidlvec.setToExternal(cipher_text, spblob_data.size() - 14 /* 1 each for version and SYNTHETIC_PASSWORD_PASSWORD_BASED and 12 for the iv */);
- begin_params.Authorization(::keystore::TAG_ALGORITHM, ::keystore::Algorithm::AES);
- begin_params.Authorization(::keystore::TAG_BLOCK_MODE, ::keystore::BlockMode::GCM);
- begin_params.Padding(::keystore::PaddingMode::NONE);
- begin_params.Authorization(::keystore::TAG_NONCE, iv_hidlvec);
- begin_params.Authorization(::keystore::TAG_MAC_LENGTH, maclen);
-
- ::keystore::hidl_vec<uint8_t> entropy; // No entropy is needed for decrypt
- entropy.resize(0);
- android::security::keymaster::KeymasterArguments empty_params;
- android::hardware::keymaster::V4_0::KeyPurpose decryptPurpose = android::hardware::keymaster::V4_0::KeyPurpose::DECRYPT;
- android::sp<android::IBinder> decryptAuthToken(new android::BBinder);
-
- android::sp<OperationResultPromise> promise = new OperationResultPromise;
- auto future = promise->get_future();
- auto binder_result = service->begin(promise, decryptAuthToken, keystore_alias16, (int32_t)decryptPurpose, true,
- android::security::keymaster::KeymasterArguments(begin_params.hidl_data()),
- entropy, -1, &error_code);
- if (!binder_result.isOk()) {
- printf("communication error while calling keystore\n");
- return disk_decryption_secret_key;
- }
- ::keystore::KeyStoreNativeReturnCode rc(error_code);
- if (!rc.isOk()) {
- printf("Keystore begin returned: %u\n", error_code);
- return disk_decryption_secret_key;
- }
- OperationResult result = future.get();
- std::map<uint64_t, android::sp<android::IBinder>> active_operations_;
- uint64_t next_virtual_handle_ = 1;
- active_operations_[next_virtual_handle_] = result.token;
-
- // The cipher.doFinal call triggers an update to the keystore followed by a finish https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java#64
- // See also https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java#208
- future = {};
- promise = new OperationResultPromise();
- future = promise->get_future();
- binder_result = service->update(promise, active_operations_[next_virtual_handle_], empty_params, cipher_text_hidlvec, &error_code);
- rc = ::keystore::KeyStoreNativeReturnCode(error_code);
- if (!rc.isOk()) {
- printf("Keystore update returned: %d\n", error_code);
- return disk_decryption_secret_key;
- }
- result = future.get();
- if (!result.resultCode.isOk()) {
- printf("update failed: %d\n", error_code);
- return disk_decryption_secret_key;
- }
-
- size_t keystore_result_size = result.data.size();
- unsigned char* keystore_result = (unsigned char*)malloc(keystore_result_size);
- if (!keystore_result) {
- printf("malloc on keystore_result\n");
- return disk_decryption_secret_key;
- }
- memcpy(keystore_result, &result.data[0], result.data.size());
- future = {};
- promise = new OperationResultPromise();
- future = promise->get_future();
-
- auto hidlSignature = blob2hidlVec("");
- auto hidlInput = blob2hidlVec(disk_decryption_secret_key);
- binder_result = service->finish(promise, active_operations_[next_virtual_handle_], empty_params, hidlInput, hidlSignature, ::keystore::hidl_vec<uint8_t>(), &error_code);
- if (!binder_result.isOk()) {
- printf("communication error while calling keystore\n");
- free(keystore_result);
- return disk_decryption_secret_key;
- }
- rc = ::keystore::KeyStoreNativeReturnCode(error_code);
- if (!rc.isOk()) {
- printf("Keystore finish returned: %d\n", error_code);
- return disk_decryption_secret_key;
- }
- result = future.get();
- if (!result.resultCode.isOk()) {
- printf("finish failed: %d\n", error_code);
- return disk_decryption_secret_key;
- }
- stop_keystore();
- /* Now we do the second decrypt call as seen in:
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r18/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java#136
- */
- const unsigned char* intermediate_iv = keystore_result;
- // printf("intermediate_iv: "); output_hex((const unsigned char*)intermediate_iv, 12); printf("\n");
- const unsigned char* intermediate_cipher_text = (const unsigned char*)keystore_result + 12; // The cipher text comes immediately after the IV
- int cipher_size = keystore_result_size - 12;
- // First we personalize as seen https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java#102
- void* personalized_application_id = PersonalizedHashBinary(PERSONALISATION_APPLICATION_ID, (const char*)application_id, application_id_size);
- if (!personalized_application_id) {
- return disk_decryption_secret_key;
- }
- // printf("personalized application id: "); output_hex((unsigned char*)personalized_application_id, SHA512_DIGEST_LENGTH); printf("\n");
- // Now we'll decrypt using openssl AES/GCM/NoPadding
- OpenSSL_add_all_ciphers();
- int actual_size=0, final_size=0;
- EVP_CIPHER_CTX *d_ctx = EVP_CIPHER_CTX_new();
- const unsigned char* key = (const unsigned char*)personalized_application_id; // The key is the now personalized copy of the application ID
- // printf("key: "); output_hex((const unsigned char*)key, 32); printf("\n");
- EVP_DecryptInit(d_ctx, EVP_aes_256_gcm(), key, intermediate_iv);
- unsigned char* secret_key = (unsigned char*)malloc(cipher_size);
- if (!secret_key) {
- printf("malloc failure on secret key\n");
- return disk_decryption_secret_key;
- }
- EVP_DecryptUpdate(d_ctx, secret_key, &actual_size, intermediate_cipher_text, cipher_size);
- unsigned char tag[AES_BLOCK_SIZE];
- EVP_CIPHER_CTX_ctrl(d_ctx, EVP_CTRL_GCM_SET_TAG, 16, tag);
- EVP_DecryptFinal_ex(d_ctx, secret_key + actual_size, &final_size);
- EVP_CIPHER_CTX_free(d_ctx);
- free(personalized_application_id);
- free(keystore_result);
- int secret_key_real_size = actual_size - 16;
- // printf("secret key: "); output_hex((const unsigned char*)secret_key, secret_key_real_size); printf("\n");
- // The payload data from the keystore update is further personalized at https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#153
- // We now have the disk decryption key!
- if (*synthetic_password_version == SYNTHETIC_PASSWORD_VERSION_V3) {
- // V3 uses SP800 instead of SHA512
- disk_decryption_secret_key = PersonalizedHashSP800(PERSONALIZATION_FBE_KEY, PERSONALISATION_CONTEXT, (const char*)secret_key, secret_key_real_size);
- } else {
- disk_decryption_secret_key = PersonalizedHash(PERSONALIZATION_FBE_KEY, (const char*)secret_key, secret_key_real_size);
- }
- // printf("disk_decryption_secret_key: '%s'\n", disk_decryption_secret_key.c_str());
- free(secret_key);
- return disk_decryption_secret_key;
- }
- return disk_decryption_secret_key;
-}
-
-}}
-
-#define PASSWORD_TOKEN_SIZE 32
-
-/* C++ replacement for
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#992
- * called here
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#813 */
-bool Get_Secdis(const std::string& spblob_path, const std::string& handle_str, std::string& secdis_data) {
- std::string secdis_file = spblob_path + handle_str + ".secdis";
- if (!android::base::ReadFileToString(secdis_file, &secdis_data)) {
- printf("Failed to read '%s'\n", secdis_file.c_str());
- return false;
- }
- // output_hex(secdis_data.data(), secdis_data.size());printf("\n");
- return true;
-}
-
-// C++ replacement for https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#1033
-userid_t fakeUid(const userid_t uid) {
- return 100000 + uid;
-}
-
-bool Is_Weaver(const std::string& spblob_path, const std::string& handle_str) {
- std::string weaver_file = spblob_path + handle_str + ".weaver";
- struct stat st;
- if (stat(weaver_file.c_str(), &st) == 0)
- return true;
- return false;
-}
-
-bool Free_Return(bool retval, void* weaver_key, password_data_struct* pwd) {
- if (weaver_key)
- free(weaver_key);
- if (pwd->salt)
- free(pwd->salt);
- if (pwd->password_handle)
- free(pwd->password_handle);
- return retval;
-}
-
-/* Decrypt_User_Synth_Pass is the TWRP C++ equivalent to spBasedDoVerifyCredential
- * https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/LockSettingsService.java#1998 */
-bool Decrypt_User_Synth_Pass(const userid_t user_id, const std::string& Password) {
- bool retval = false;
- void* weaver_key = NULL;
- password_data_struct pwd;
- pwd.salt = NULL;
- pwd.salt_len = 0;
- pwd.password_handle = NULL;
- pwd.handle_len = 0;
- char application_id[PASSWORD_TOKEN_SIZE + SHA512_DIGEST_LENGTH];
-
- uint32_t auth_token_len = 0;
-
- std::string secret; // this will be the disk decryption key that is sent to vold
- std::string token = "!"; // there is no token used for this kind of decrypt, key escrow is handled by weaver
- int flags = android::os::IVold::STORAGE_FLAG_CE;
- char spblob_path_char[PATH_MAX];
- sprintf(spblob_path_char, "/data/system_de/%d/spblob/", user_id);
- std::string spblob_path = spblob_path_char;
- long handle = 0;
- std::string handle_str;
- // Get the handle: https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/LockSettingsService.java#2017
- if (!Find_Handle(spblob_path, handle_str)) {
- printf("Error getting handle\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- // printf("Handle is '%s'\n", handle_str.c_str());
- // Now we begin driving unwrapPasswordBasedSyntheticPassword from: https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#758
- // First we read the password data which contains scrypt parameters
- if (!Get_Password_Data(spblob_path, handle_str, &pwd)) {
- printf("Failed to Get_Password_Data\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- // printf("pwd N %i R %i P %i salt ", pwd.scryptN, pwd.scryptR, pwd.scryptP); output_hex((char*)pwd.salt, pwd.salt_len); printf("\n");
- unsigned char password_token[PASSWORD_TOKEN_SIZE];
- // printf("Password: '%s'\n", Password.c_str());
- // The password token is the password scrypted with the parameters from the password data file
- if (!Get_Password_Token(&pwd, Password, &password_token[0])) {
- printf("Failed to Get_Password_Token\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- // output_hex(&password_token[0], PASSWORD_TOKEN_SIZE);printf("\n");
- if (Is_Weaver(spblob_path, handle_str)) {
- printf("using weaver\n");
- // BEGIN PIXEL 2 WEAVER
- // Get the weaver data from the .weaver file which tells us which slot to use when we ask weaver for the escrowed key
- // https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#768
- weaver_data_struct wd;
- if (!Get_Weaver_Data(spblob_path, handle_str, &wd)) {
- printf("Failed to get weaver data\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- // The weaver key is the the password token prefixed with "weaver-key" padded to 128 with nulls with the password token appended then SHA512
- // https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#1059
- weaver_key = PersonalizedHashBinary(PERSONALISATION_WEAVER_KEY, (char*)&password_token[0], PASSWORD_TOKEN_SIZE);
- if (!weaver_key) {
- printf("malloc error getting weaver_key\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- // Now we start driving weaverVerify: https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#343
- // Called from https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#776
- android::vold::Weaver weaver;
- if (!weaver) {
- printf("Failed to get weaver service\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- // Get the key size from weaver service
- uint32_t weaver_key_size = 0;
- if (!weaver.GetKeySize(&weaver_key_size)) {
- printf("Failed to get weaver key size\n");
- return Free_Return(retval, weaver_key, &pwd);
- } else {
- printf("weaver key size is %u\n", weaver_key_size);
- }
- // printf("weaver key: "); output_hex((unsigned char*)weaver_key, weaver_key_size); printf("\n");
- // Send the slot from the .weaver file, the computed weaver key, and get the escrowed key data
- std::vector<uint8_t> weaver_payload;
- // TODO: we should return more information about the status including time delays before the next retry
- if (!weaver.WeaverVerify(wd.slot, weaver_key, &weaver_payload)) {
- printf("failed to weaver verify\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- // printf("weaver payload: "); output_hex(&weaver_payload); printf("\n");
- // Done with weaverVerify
- // Now we will compute the application ID
- // https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#964
- // Called from https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#780
- // The escrowed weaver key data is prefixed with "weaver-pwd" padded to 128 with nulls with the weaver payload appended then SHA512
- void* weaver_secret = PersonalizedHashBinary(PERSONALISATION_WEAVER_PASSWORD, (const char*)weaver_payload.data(), weaver_payload.size());
- // printf("weaver secret: "); output_hex((unsigned char*)weaver_secret, SHA512_DIGEST_LENGTH); printf("\n");
- // The application ID is the password token and weaver secret appended to each other
- memcpy((void*)&application_id[0], (void*)&password_token[0], PASSWORD_TOKEN_SIZE);
- memcpy((void*)&application_id[PASSWORD_TOKEN_SIZE], weaver_secret, SHA512_DIGEST_LENGTH);
- // printf("application ID: "); output_hex((unsigned char*)application_id, PASSWORD_TOKEN_SIZE + SHA512_DIGEST_LENGTH); printf("\n");
- // END PIXEL 2 WEAVER
- } else {
- printf("using secdis\n");
- std::string secdis_data;
- if (!Get_Secdis(spblob_path, handle_str, secdis_data)) {
- printf("Failed to get secdis data\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- void* secdiscardable = PersonalizedHashBinary(PERSONALISATION_SECDISCARDABLE, (char*)secdis_data.data(), secdis_data.size());
- if (!secdiscardable) {
- printf("malloc error getting secdiscardable\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- memcpy((void*)&application_id[0], (void*)&password_token[0], PASSWORD_TOKEN_SIZE);
- memcpy((void*)&application_id[PASSWORD_TOKEN_SIZE], secdiscardable, SHA512_DIGEST_LENGTH);
-
- int ret = -1;
- bool request_reenroll = false;
- android::sp<android::hardware::gatekeeper::V1_0::IGatekeeper> gk_device;
- gk_device = ::android::hardware::gatekeeper::V1_0::IGatekeeper::getService();
- if (gk_device == nullptr) {
- printf("failed to get gatekeeper service\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- if (pwd.handle_len <= 0) {
- printf("no password handle supplied\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- android::hardware::hidl_vec<uint8_t> pwd_handle_hidl;
- pwd_handle_hidl.setToExternal(const_cast<uint8_t *>((const uint8_t *)pwd.password_handle), pwd.handle_len);
- void* gk_pwd_token = PersonalizedHashBinary(PERSONALIZATION_USER_GK_AUTH, (char*)&password_token[0], PASSWORD_TOKEN_SIZE);
- if (!gk_pwd_token) {
- printf("malloc error getting gatekeeper_key\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- android::hardware::hidl_vec<uint8_t> gk_pwd_token_hidl;
- gk_pwd_token_hidl.setToExternal(const_cast<uint8_t *>((const uint8_t *)gk_pwd_token), SHA512_DIGEST_LENGTH);
- android::hardware::Return<void> hwRet =
- gk_device->verify(fakeUid(user_id), 0 /* challange */,
- pwd_handle_hidl,
- gk_pwd_token_hidl,
- [&ret, &request_reenroll, &auth_token_len]
- (const android::hardware::gatekeeper::V1_0::GatekeeperResponse &rsp) {
- ret = static_cast<int>(rsp.code); // propagate errors
- if (rsp.code >= android::hardware::gatekeeper::V1_0::GatekeeperStatusCode::STATUS_OK) {
- auth_token_len = rsp.data.size();
- request_reenroll = (rsp.code == android::hardware::gatekeeper::V1_0::GatekeeperStatusCode::STATUS_REENROLL);
- ret = 0; // all success states are reported as 0
- // The keystore refuses to allow the root user to supply auth tokens, so we write the auth token to a file here and later
- // run a separate service that runs as the system user to add the auth token. We wait for the auth token file to be
- // deleted by the keymaster_auth service and check for a /auth_error file in case of errors. We quit after a while seconds if
- // the /auth_token file never gets deleted.
- unlink("/auth_token");
- FILE* auth_file = fopen("/auth_token","wb");
- if (auth_file != NULL) {
- fwrite(rsp.data.data(), sizeof(uint8_t), rsp.data.size(), auth_file);
- fclose(auth_file);
- } else {
- printf("failed to open /auth_token for writing\n");
- ret = -2;
- }
- } else if (rsp.code == android::hardware::gatekeeper::V1_0::GatekeeperStatusCode::ERROR_RETRY_TIMEOUT && rsp.timeout > 0) {
- ret = rsp.timeout;
- }
- }
- );
- free(gk_pwd_token);
- if (!hwRet.isOk() || ret != 0) {
- printf("gatekeeper verification failed\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- }
- // Now we will handle https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#816
- // Plus we will include the last bit that computes the disk decrypt key found in:
- // https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r23/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java#153
- secret = android::keystore::unwrapSyntheticPasswordBlob(spblob_path, handle_str, user_id, (const void*)&application_id[0],
- PASSWORD_TOKEN_SIZE + SHA512_DIGEST_LENGTH, auth_token_len);
- if (!secret.size()) {
- printf("failed to unwrapSyntheticPasswordBlob\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
-
- if (!fscrypt_unlock_user_key(user_id, 0, token.c_str(), secret.c_str())) {
- printf("fscrypt_unlock_user_key returned fail\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
-
- if (!fscrypt_prepare_user_storage("", user_id, 0, flags)) {
- printf("failed to fscrypt_prepare_user_storage\n");
- return Free_Return(retval, weaver_key, &pwd);
- }
- printf("User %i Decrypted Successfully!\n", user_id);
- retval = true;
- return Free_Return(retval, weaver_key, &pwd);
-}
-
-int Get_Password_Type(const userid_t user_id, std::string& filename) {
- struct stat st;
- char spblob_path_char[PATH_MAX];
- sprintf(spblob_path_char, "/data/system_de/%d/spblob/", user_id);
- if (stat(spblob_path_char, &st) == 0) {
- printf("Using synthetic password method\n");
- std::string spblob_path = spblob_path_char;
- std::string handle_str;
- if (!Find_Handle(spblob_path, handle_str)) {
- printf("Error getting handle\n");
- return 0;
- }
- printf("Handle is '%s'\n", handle_str.c_str());
- password_data_struct pwd;
- if (!Get_Password_Data(spblob_path, handle_str, &pwd)) {
- printf("Failed to Get_Password_Data\n");
- return 0;
- }
- // In Android type 1 is pattern
- // In Android <11 type 2 is PIN or password
- // In Android 11+ type 3 is PIN and type 4 is password
- if (pwd.password_type == 2) {
- printf("password type: password/PIN\n");
- return 1; // In TWRP this means password or PIN (Android <11)
- } else if (pwd.password_type == 4) {
- printf("password type: password\n");
- return 1; // In TWRP this means password
- } else if (pwd.password_type == 1) {
- printf("password type: pattern\n");
- return 2; // In TWRP this means pattern
- } else if (pwd.password_type == 3) {
- printf("password type: PIN\n");
- return 3; // In TWRP this means PIN
- }
- printf("using default password\n");
- return 0; // We'll try the default password
- }
- std::string path;
- if (user_id == 0) {
- path = "/data/system/";
- } else {
- char user_id_str[5];
- sprintf(user_id_str, "%i", user_id);
- path = "/data/system/users/";
- path += user_id_str;
- path += "/";
- }
- filename = path + "gatekeeper.password.key";
- if (stat(filename.c_str(), &st) == 0 && st.st_size > 0)
- return 1;
- filename = path + "gatekeeper.pattern.key";
- if (stat(filename.c_str(), &st) == 0 && st.st_size > 0)
- return 2;
- printf("Unable to locate gatekeeper password file '%s'\n", filename.c_str());
- filename = "";
- return 0;
-}
-
-bool Decrypt_User(const userid_t user_id, const std::string& Password) {
- uint8_t *auth_token;
- uint32_t auth_token_len;
- int ret;
-
- struct stat st;
- if (user_id > 9999) {
- printf("user_id is too big\n");
- return false;
- }
- std::string filename;
- bool Default_Password = (Password == "!");
- if (Get_Password_Type(user_id, filename) == 0 && !Default_Password) {
- printf("Unknown password type\n");
- return false;
- }
-
- int flags = android::os::IVold::STORAGE_FLAG_CE;
-
- if (Default_Password) {
- if (!fscrypt_unlock_user_key(user_id, 0, "!", "!")) {
- printf("unlock_user_key returned fail\n");
- return false;
- }
- if (!fscrypt_prepare_user_storage("", user_id, 0, flags)) {
- printf("failed to fscrypt_prepare_user_storage\n");
- return false;
- }
- printf("User %i Decrypted Successfully!\n", user_id);
- return true;
- }
- if (stat("/data/system_de/0/spblob", &st) == 0) {
- printf("Using synthetic password method\n");
- return Decrypt_User_Synth_Pass(user_id, Password);
- }
- // printf("password filename is '%s'\n", filename.c_str());
- if (stat(filename.c_str(), &st) != 0) {
- printf("error stat'ing key file: %s\n", strerror(errno));
- return false;
- }
- std::string handle;
- if (!android::base::ReadFileToString(filename, &handle)) {
- printf("Failed to read '%s'\n", filename.c_str());
- return false;
- }
- bool should_reenroll;
- bool request_reenroll = false;
- android::sp<android::hardware::gatekeeper::V1_0::IGatekeeper> gk_device;
- gk_device = ::android::hardware::gatekeeper::V1_0::IGatekeeper::getService();
- if (gk_device == nullptr)
- return false;
- android::hardware::hidl_vec<uint8_t> curPwdHandle;
- curPwdHandle.setToExternal(const_cast<uint8_t *>((const uint8_t *)handle.c_str()), st.st_size);
- android::hardware::hidl_vec<uint8_t> enteredPwd;
- enteredPwd.setToExternal(const_cast<uint8_t *>((const uint8_t *)Password.c_str()), Password.size());
-
- android::hardware::Return<void> hwRet =
- gk_device->verify(user_id, 0 /* challange */,
- curPwdHandle,
- enteredPwd,
- [&ret, &request_reenroll, &auth_token, &auth_token_len]
- (const android::hardware::gatekeeper::V1_0::GatekeeperResponse &rsp) {
- ret = static_cast<int>(rsp.code); // propagate errors
- if (rsp.code >= android::hardware::gatekeeper::V1_0::GatekeeperStatusCode::STATUS_OK) {
- auth_token = new uint8_t[rsp.data.size()];
- auth_token_len = rsp.data.size();
- memcpy(auth_token, rsp.data.data(), auth_token_len);
- request_reenroll = (rsp.code == android::hardware::gatekeeper::V1_0::GatekeeperStatusCode::STATUS_REENROLL);
- ret = 0; // all success states are reported as 0
- } else if (rsp.code == android::hardware::gatekeeper::V1_0::GatekeeperStatusCode::ERROR_RETRY_TIMEOUT && rsp.timeout > 0) {
- ret = rsp.timeout;
- }
- }
- );
- if (!hwRet.isOk()) {
- return false;
- }
-
- char token_hex[(auth_token_len*2)+1];
- token_hex[(auth_token_len*2)] = 0;
- uint32_t i;
- for (i=0;i<auth_token_len;i++) {
- sprintf(&token_hex[2*i], "%02X", auth_token[i]);
- }
- // The secret is "Android FBE credential hash" plus appended 0x00 to reach 128 bytes then append the user's password then feed that to sha512sum
- std::string secret = HashPassword(Password);
- if (!fscrypt_unlock_user_key(user_id, 0, token_hex, secret.c_str())) {
- printf("fscrypt_unlock_user_key returned fail\n");
- return false;
- }
-
- if (!fscrypt_prepare_user_storage("", user_id, 0, flags)) {
- printf("failed to fscrypt_prepare_user_storage\n");
- return false;
- }
- printf("User %i Decrypted Successfully!\n", user_id);
- return true;
-}
diff --git a/crypto/fscrypt/Decrypt.h b/crypto/fscrypt/Decrypt.h
deleted file mode 100755
index f397749..0000000
--- a/crypto/fscrypt/Decrypt.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2015 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 <stdbool.h>
-#include <sys/cdefs.h>
-
-#include <cutils/multiuser.h>
-
-#include <string>
-
-__BEGIN_DECLS
-
-// NOTE: keep in sync with StorageManager
-static constexpr int FLAG_STORAGE_DE = 1 << 0;
-static constexpr int FLAG_STORAGE_CE = 1 << 1;
-// For 9.0 Ext4CryptPie.cpp
-static constexpr int STORAGE_FLAG_DE = 1;
-static constexpr int STORAGE_FLAG_CE = 2;
-
-
-int Get_Password_Type(const userid_t user_id, std::string& filename);
-bool Decrypt_DE();
-bool Decrypt_User(const userid_t user_id, const std::string& Password);
-__END_DECLS
diff --git a/crypto/fscrypt/EncryptInplace.cpp b/crypto/fscrypt/EncryptInplace.cpp
deleted file mode 100644
index 9d304da..0000000
--- a/crypto/fscrypt/EncryptInplace.cpp
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * Copyright (C) 2016 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 "EncryptInplace.h"
-
-#include <ext4_utils/ext4.h>
-#include <ext4_utils/ext4_utils.h>
-#include <f2fs_sparseblock.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-
-#include <algorithm>
-
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-
-// HORRIBLE HACK, FIXME
-#include "cryptfs.h"
-
-// FIXME horrible cut-and-paste code
-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));
-}
-
-#define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / CRYPT_SECTOR_SIZE)
-
-/* aligned 32K writes tends to make flash happy.
- * SD card association recommends it.
- */
-#ifndef CONFIG_HW_DISK_ENCRYPTION
-#define BLOCKS_AT_A_TIME 8
-#else
-#define BLOCKS_AT_A_TIME 1024
-#endif
-
-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;
- const char* real_blkdev;
- const char* crypto_blkdev;
- int count;
- off64_t offset;
- char* buffer;
- off64_t last_written_sector;
- int completed;
- time_t time_started;
- int remaining_time;
- bool set_progress_properties;
-};
-
-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->set_progress_properties) return;
-
- if (data->new_pct > data->cur_pct) {
- char buf[8];
- data->cur_pct = data->new_pct;
- snprintf(buf, sizeof(buf), "%" PRId64, data->cur_pct);
- android::base::SetProperty("vold.encrypt_progress", buf);
- }
-
- if (data->cur_pct >= 5) {
- struct timespec time_now;
- if (clock_gettime(CLOCK_MONOTONIC, &time_now)) {
- LOG(WARNING) << "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);
- android::base::SetProperty("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)) {
- LOG(INFO) << "Encrypted to sector " << offset / info.block_size * CRYPT_SECTOR_SIZE;
- offset = -1;
- }
-
- // Need to start new 'Encrypting from' log?
- if (!completed && offset != data->offset) {
- LOG(INFO) << "Encrypting from sector " << 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;
- }
-
- LOG(DEBUG) << "Copying " << data->count << " blocks at offset " << data->offset;
-
- if (pread64(data->realfd, data->buffer, info.block_size * data->count, data->offset) <= 0) {
- LOG(ERROR) << "Error reading real_blkdev " << data->real_blkdev << " for inplace encrypt";
- return -1;
- }
-
- if (pwrite64(data->cryptofd, data->buffer, info.block_size * data->count, data->offset) <= 0) {
- LOG(ERROR) << "Error writing crypto_blkdev " << data->crypto_blkdev
- << " for inplace encrypt";
- 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 = (char*)malloc(info.block_size * BLOCKS_AT_A_TIME);
- if (!data->buffer) {
- LOG(ERROR) << "Failed to allocate crypto buffer";
- goto errout;
- }
-
- block_bitmap = (u8*)malloc(info.block_size);
- if (!block_bitmap) {
- LOG(ERROR) << "failed to allocate block bitmap";
- goto errout;
- }
-
- for (i = 0; i < aux_info.groups; ++i) {
- LOG(INFO) << "Encrypting group " << i;
-
- u32 first_block = aux_info.first_data_block + i * info.blocks_per_group;
- u32 block_count = std::min(info.blocks_per_group, (u32)(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) {
- LOG(ERROR) << "failed to read all of block group bitmap " << i;
- goto errout;
- }
-
- offset = (u64)info.block_size * first_block;
-
- data->count = 0;
-
- for (block = 0; block < block_count; block++) {
- int used = (aux_info.bg_desc[i].bg_flags & EXT4_BG_BLOCK_UNINIT)
- ? 0
- : 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 (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(const char* crypto_blkdev, const char* real_blkdev,
- off64_t size, off64_t* size_already_done, off64_t tot_size,
- off64_t previously_encrypted_upto,
- bool set_progress_properties) {
- u32 i;
- struct encryptGroupsData data;
- int rc; // Can't initialize without causing warning -Wclobbered
- int retries = RETRY_MOUNT_ATTEMPTS;
- struct timespec time_started = {0};
-
- if (previously_encrypted_upto > *size_already_done) {
- LOG(DEBUG) << "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;
- data.set_progress_properties = set_progress_properties;
-
- LOG(DEBUG) << "Opening" << real_blkdev;
- if ((data.realfd = open(real_blkdev, O_RDWR | O_CLOEXEC)) < 0) {
- PLOG(ERROR) << "Error opening real_blkdev " << real_blkdev << " for inplace encrypt";
- rc = -1;
- goto errout;
- }
-
- LOG(DEBUG) << "Opening" << crypto_blkdev;
- // Wait until the block device appears. Re-use the mount retry values since it is reasonable.
- while ((data.cryptofd = open(crypto_blkdev, O_WRONLY | O_CLOEXEC)) < 0) {
- if (--retries) {
- PLOG(ERROR) << "Error opening crypto_blkdev " << crypto_blkdev
- << " for ext4 inplace encrypt, retrying";
- sleep(RETRY_MOUNT_DELAY_SECONDS);
- } else {
- PLOG(ERROR) << "Error opening crypto_blkdev " << crypto_blkdev
- << " for ext4 inplace encrypt";
- rc = ENABLE_INPLACE_ERR_DEV;
- goto errout;
- }
- }
-
- if (setjmp(setjmp_env)) { // NOLINT
- LOG(ERROR) << "Reading ext4 extent caused an exception";
- rc = -1;
- goto errout;
- }
-
- if (read_ext(data.realfd, 0) != 0) {
- LOG(ERROR) << "Failed to read ext4 extent";
- 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;
-
- LOG(INFO) << "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;
-
- if (clock_gettime(CLOCK_MONOTONIC, &time_started)) {
- LOG(WARNING) << "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) {
- LOG(ERROR) << "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)) {
- LOG(INFO) << "Encrypted to block " << last_block;
- last_block = -1;
- }
-
- // Need to start new 'Encrypting from' log?
- if (!completed && (last_block == (u64)-1 || block != last_block + 1)) {
- LOG(INFO) << "Encrypting from block " << 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) {
- LOG(ERROR) << "Error reading real_blkdev " << priv_dat->crypto_blkdev
- << " for f2fs inplace encrypt";
- return -1;
- }
-
- if (pwrite64(priv_dat->cryptofd, priv_dat->buffer, CRYPT_INPLACE_BUFSIZE, offset) <= 0) {
- LOG(ERROR) << "Error writing crypto_blkdev " << priv_dat->crypto_blkdev
- << " for f2fs inplace encrypt";
- return -1;
- } else {
- log_progress_f2fs(pos, false);
- }
-
- return 0;
-}
-
-static int cryptfs_enable_inplace_f2fs(const char* crypto_blkdev, const char* real_blkdev,
- off64_t size, off64_t* size_already_done, off64_t tot_size,
- off64_t previously_encrypted_upto,
- bool set_progress_properties) {
- struct encryptGroupsData data;
- struct f2fs_info* f2fs_info = NULL;
- int rc = ENABLE_INPLACE_ERR_OTHER;
- struct timespec time_started = {0};
-
- if (previously_encrypted_upto > *size_already_done) {
- LOG(DEBUG) << "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.set_progress_properties = set_progress_properties;
- data.realfd = -1;
- data.cryptofd = -1;
- if ((data.realfd = open64(real_blkdev, O_RDWR | O_CLOEXEC)) < 0) {
- PLOG(ERROR) << "Error opening real_blkdev " << real_blkdev << " for f2fs inplace encrypt";
- goto errout;
- }
- if ((data.cryptofd = open64(crypto_blkdev, O_WRONLY | O_CLOEXEC)) < 0) {
- PLOG(ERROR) << "Error opening crypto_blkdev " << crypto_blkdev
- << " for f2fs inplace encrypt";
- 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;
- if (clock_gettime(CLOCK_MONOTONIC, &time_started)) {
- LOG(WARNING) << "Error getting time at start";
- // Note - continue anyway - we'll run with 0
- }
- data.time_started = time_started.tv_sec;
- data.remaining_time = -1;
-
-
- data.buffer = (char*)malloc(f2fs_info->block_size);
- if (!data.buffer) {
- LOG(ERROR) << "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) {
- LOG(ERROR) << "Error in running over f2fs blocks";
- rc = ENABLE_INPLACE_ERR_OTHER;
- goto errout;
- }
-
- *size_already_done += size;
- rc = 0;
-
-errout:
- if (rc) LOG(ERROR) << "Failed to encrypt f2fs filesystem on " << 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(const char* crypto_blkdev, const char* real_blkdev,
- off64_t size, off64_t* size_already_done, off64_t tot_size,
- off64_t previously_encrypted_upto,
- bool set_progress_properties) {
- 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 | O_CLOEXEC)) < 0) {
- PLOG(ERROR) << "Error opening real_blkdev " << real_blkdev << " for inplace encrypt";
- return ENABLE_INPLACE_ERR_OTHER;
- }
-
- if ((cryptofd = open(crypto_blkdev, O_WRONLY | O_CLOEXEC)) < 0) {
- PLOG(ERROR) << "Error opening crypto_blkdev " << crypto_blkdev << " for inplace encrypt";
- 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;
-
- LOG(ERROR) << "Encrypting filesystem in place...";
-
- i = previously_encrypted_upto + 1 - *size_already_done;
-
- if (lseek64(realfd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) {
- PLOG(ERROR) << "Cannot seek to previously encrypted point on " << real_blkdev;
- goto errout;
- }
-
- if (lseek64(cryptofd, i * CRYPT_SECTOR_SIZE, SEEK_SET) < 0) {
- PLOG(ERROR) << "Cannot seek to previously encrypted point on " << crypto_blkdev;
- goto errout;
- }
-
- for (; i < size && i % CRYPT_SECTORS_PER_BUFSIZE != 0; ++i) {
- if (unix_read(realfd, buf, CRYPT_SECTOR_SIZE) <= 0) {
- PLOG(ERROR) << "Error reading initial sectors from real_blkdev " << real_blkdev
- << " for inplace encrypt";
- goto errout;
- }
- if (unix_write(cryptofd, buf, CRYPT_SECTOR_SIZE) <= 0) {
- PLOG(ERROR) << "Error writing initial sectors to crypto_blkdev " << crypto_blkdev
- << " for inplace encrypt";
- goto errout;
- } else {
- LOG(INFO) << "Encrypted 1 block at " << 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 (set_progress_properties && new_pct > cur_pct) {
- char property_buf[8];
-
- cur_pct = new_pct;
- snprintf(property_buf, sizeof(property_buf), "%" PRId64, cur_pct);
- android::base::SetProperty("vold.encrypt_progress", property_buf);
- }
- if (unix_read(realfd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
- PLOG(ERROR) << "Error reading real_blkdev " << real_blkdev << " for inplace encrypt";
- goto errout;
- }
- if (unix_write(cryptofd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
- PLOG(ERROR) << "Error writing crypto_blkdev " << crypto_blkdev << " for inplace encrypt";
- goto errout;
- } else {
- LOG(DEBUG) << "Encrypted " << CRYPT_SECTORS_PER_BUFSIZE << " block at "
- << i * CRYPT_SECTORS_PER_BUFSIZE;
- }
- }
-
- /* Do any remaining sectors */
- for (i = 0; i < remainder; i++) {
- if (unix_read(realfd, buf, CRYPT_SECTOR_SIZE) <= 0) {
- LOG(ERROR) << "Error reading final sectors from real_blkdev " << real_blkdev
- << " for inplace encrypt";
- goto errout;
- }
- if (unix_write(cryptofd, buf, CRYPT_SECTOR_SIZE) <= 0) {
- LOG(ERROR) << "Error writing final sectors to crypto_blkdev " << crypto_blkdev
- << " for inplace encrypt";
- goto errout;
- } else {
- LOG(INFO) << "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 */
-int cryptfs_enable_inplace(const char* crypto_blkdev, const char* real_blkdev, off64_t size,
- off64_t* size_already_done, off64_t tot_size,
- off64_t previously_encrypted_upto, bool set_progress_properties) {
- int rc_ext4, rc_f2fs, rc_full;
- LOG(DEBUG) << "cryptfs_enable_inplace(" << crypto_blkdev << ", " << real_blkdev << ", " << size
- << ", " << size_already_done << ", " << tot_size << ", " << previously_encrypted_upto
- << ", " << set_progress_properties << ")";
- if (previously_encrypted_upto) {
- LOG(DEBUG) << "Continuing encryption from " << previously_encrypted_upto;
- }
-
- if (*size_already_done + size < previously_encrypted_upto) {
- LOG(DEBUG) << "cryptfs_enable_inplace already done";
- *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,
- set_progress_properties)) == 0) {
- LOG(DEBUG) << "cryptfs_enable_inplace_ext4 success";
- return 0;
- }
- LOG(DEBUG) << "cryptfs_enable_inplace_ext4()=" << rc_ext4;
-
- if ((rc_f2fs = cryptfs_enable_inplace_f2fs(crypto_blkdev, real_blkdev, size, size_already_done,
- tot_size, previously_encrypted_upto,
- set_progress_properties)) == 0) {
- LOG(DEBUG) << "cryptfs_enable_inplace_f2fs success";
- return 0;
- }
- LOG(DEBUG) << "cryptfs_enable_inplace_f2fs()=" << rc_f2fs;
-
- rc_full =
- cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev, size, size_already_done, tot_size,
- previously_encrypted_upto, set_progress_properties);
- LOG(DEBUG) << "cryptfs_enable_inplace_full()=" << 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) {
- LOG(DEBUG) << "ENABLE_INPLACE_ERR_DEV";
- return ENABLE_INPLACE_ERR_DEV;
- }
- return rc_full;
-}
diff --git a/crypto/fscrypt/EncryptInplace.h b/crypto/fscrypt/EncryptInplace.h
deleted file mode 100644
index a2b46cf..0000000
--- a/crypto/fscrypt/EncryptInplace.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 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 _ENCRYPT_INPLACE_H
-#define _ENCRYPT_INPLACE_H
-
-#include <sys/types.h>
-
-#define CRYPT_INPLACE_BUFSIZE 4096
-#define CRYPT_SECTOR_SIZE 512
-#define RETRY_MOUNT_ATTEMPTS 10
-#define RETRY_MOUNT_DELAY_SECONDS 1
-
-/* Return values for cryptfs_enable_inplace() */
-#define ENABLE_INPLACE_OK 0
-#define ENABLE_INPLACE_ERR_OTHER (-1)
-#define ENABLE_INPLACE_ERR_DEV (-2) /* crypto_blkdev issue */
-
-int cryptfs_enable_inplace(const char* crypto_blkdev, const char* real_blkdev, off64_t size,
- off64_t* size_already_done, off64_t tot_size,
- off64_t previously_encrypted_upto, bool set_progress_properties);
-
-#endif
diff --git a/crypto/fscrypt/FsCrypt.cpp b/crypto/fscrypt/FsCrypt.cpp
deleted file mode 100755
index a2049a2..0000000
--- a/crypto/fscrypt/FsCrypt.cpp
+++ /dev/null
@@ -1,1048 +0,0 @@
-/*
- * Copyright (C) 2015 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 "FsCrypt.h"
-
-#include "KeyStorage.h"
-#include "KeyUtil.h"
-#include "Utils.h"
-#include "VoldUtil.h"
-
-#include <algorithm>
-#include <map>
-#include <optional>
-#include <set>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <selinux/android.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <private/android_filesystem_config.h>
-#include <private/android_projectid_config.h>
-
-#include "android/os/IVold.h"
-
-#define EMULATED_USES_SELINUX 0
-#define MANAGE_MISC_DIRS 0
-
-#include <cutils/fs.h>
-#include <cutils/properties.h>
-
-#include <fscrypt/fscrypt.h>
-#include <keyutils.h>
-#include <libdm/dm.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-
-#include "fscrypt-common.h"
-
-using android::base::Basename;
-using android::base::Realpath;
-using android::base::StartsWith;
-using android::base::StringPrintf;
-using android::fs_mgr::GetEntryForMountPoint;
-using ::BuildDataPath;
-using ::IsFilesystemSupported;
-using ::kEmptyAuthentication;
-using ::KeyBuffer;
-using ::KeyGeneration;
-using ::retrieveKey;
-using ::retrieveOrGenerateKey;
-using ::SetQuotaInherit;
-using ::SetQuotaProjectId;
-using ::writeStringToFile;
-using namespace android::fscrypt;
-using namespace android::dm;
-
-// Map user ids to encryption policies
-std::map<userid_t, EncryptionPolicy> s_de_policies;
-std::map<userid_t, EncryptionPolicy> s_ce_policies;
-std::string de_key_raw_ref;
-
-namespace {
-
-const std::string device_key_dir = std::string() + DATA_MNT_POINT + fscrypt_unencrypted_folder;
-const std::string device_key_path = device_key_dir + "/key";
-const std::string device_key_temp = device_key_dir + "/temp";
-
-const std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys";
-const std::string user_key_temp = user_key_dir + "/temp";
-const std::string prepare_subdirs_path = "/system/bin/vold_prepare_subdirs";
-
-const std::string systemwide_volume_key_dir =
- std::string() + DATA_MNT_POINT + "/misc/vold/volume_keys";
-
-// Some users are ephemeral, don't try to wipe their keys from disk
-std::set<userid_t> s_ephemeral_users;
-
-} // namespace
-
-// Returns KeyGeneration suitable for key as described in EncryptionOptions
-static KeyGeneration makeGen(const EncryptionOptions& options) {
- return KeyGeneration{FSCRYPT_MAX_KEY_SIZE, true, options.use_hw_wrapped_key};
-}
-
-static bool fscrypt_is_emulated() {
- return property_get_bool("persist.sys.emulate_fbe", false);
-}
-
-static const char* escape_empty(const std::string& value) {
- return value.empty() ? "null" : value.c_str();
-}
-
-static std::string get_de_key_path(userid_t user_id) {
- return StringPrintf("%s/de/%d", user_key_dir.c_str(), user_id);
-}
-
-static std::string get_ce_key_directory_path(userid_t user_id) {
- return StringPrintf("%s/ce/%d", user_key_dir.c_str(), user_id);
-}
-
-// Returns the keys newest first
-static std::vector<std::string> get_ce_key_paths(const std::string& directory_path) {
- auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(directory_path.c_str()), closedir);
- if (!dirp) {
- PLOG(ERROR) << "Unable to open ce key directory: " + directory_path;
- return std::vector<std::string>();
- }
- std::vector<std::string> result;
- for (;;) {
- errno = 0;
- auto const entry = readdir(dirp.get());
- if (!entry) {
- if (errno) {
- PLOG(ERROR) << "Unable to read ce key directory: " + directory_path;
- return std::vector<std::string>();
- }
- break;
- }
- if (entry->d_type != DT_DIR || entry->d_name[0] != 'c') {
- LOG(INFO) << "Skipping non-key " << entry->d_name;
- continue;
- }
- result.emplace_back(directory_path + "/" + entry->d_name);
- }
- std::sort(result.begin(), result.end());
- std::reverse(result.begin(), result.end());
- return result;
-}
-
-static std::string get_ce_key_current_path(const std::string& directory_path) {
- return directory_path + "/current";
-}
-
-static bool get_ce_key_new_path(const std::string& directory_path,
- const std::vector<std::string>& paths, std::string* ce_key_path) {
- if (paths.empty()) {
- *ce_key_path = get_ce_key_current_path(directory_path);
- return true;
- }
- for (unsigned int i = 0; i < UINT_MAX; i++) {
- auto const candidate = StringPrintf("%s/cx%010u", directory_path.c_str(), i);
- if (paths[0] < candidate) {
- *ce_key_path = candidate;
- return true;
- }
- }
- return false;
-}
-
-// Discard all keys but the named one; rename it to canonical name.
-// No point in acting on errors in this; ignore them.
-static void fixate_user_ce_key(const std::string& directory_path, const std::string& to_fix,
- const std::vector<std::string>& paths) {
- for (auto const other_path : paths) {
- if (other_path != to_fix) {
- ::destroyKey(other_path);
- }
- }
- auto const current_path = get_ce_key_current_path(directory_path);
- if (to_fix != current_path) {
- LOG(INFO) << "Renaming " << to_fix << " to " << current_path;
- if (rename(to_fix.c_str(), current_path.c_str()) != 0) {
- PLOG(WARNING) << "Unable to rename " << to_fix << " to " << current_path;
- return;
- }
- }
- ::FsyncDirectory(directory_path);
-}
-
-static bool read_and_fixate_user_ce_key(userid_t user_id,
- const ::KeyAuthentication& auth,
- KeyBuffer* ce_key) {
- auto const directory_path = get_ce_key_directory_path(user_id);
- auto const paths = get_ce_key_paths(directory_path);
- for (auto const ce_key_path : paths) {
- LOG(INFO) << "Trying user CE key " << ce_key_path;
- if (retrieveKey(ce_key_path, auth, ce_key, true)) {
- LOG(INFO) << "Successfully retrieved key";
- fixate_user_ce_key(directory_path, ce_key_path, paths);
- return true;
- }
- }
- LOG(ERROR) << "Failed to find working ce key for user " << user_id;
- return false;
-}
-
-static bool IsEmmcStorage(const std::string& blk_device) {
- // Handle symlinks.
- std::string real_path;
- if (!Realpath(blk_device, &real_path)) {
- real_path = blk_device;
- }
-
- // Handle logical volumes.
- auto& dm = DeviceMapper::Instance();
- for (;;) {
- auto parent = dm.GetParentBlockDeviceByPath(real_path);
- if (!parent.has_value()) break;
- real_path = *parent;
- }
-
- // Now we should have the "real" block device.
- LOG(INFO) << "IsEmmcStorage(): blk_device = " << blk_device << ", real_path=" << real_path;
- return StartsWith(Basename(real_path), "mmcblk");
-}
-
-// Retrieve the options to use for encryption policies on the /data filesystem.
-static bool get_data_file_encryption_options(EncryptionOptions* options) {
- if (fstab_default.empty()) {
- if (!ReadDefaultFstab(&fstab_default)) {
- PLOG(ERROR) << "Failed to open default fstab";
- return false;
- }
- }
- auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
- if (entry == nullptr) {
- LOG(ERROR) << "No mount point entry for " << DATA_MNT_POINT;
- return false;
- }
- if (!ParseOptions(entry->encryption_options, options)) {
- LOG(ERROR) << "Unable to parse encryption options for " << DATA_MNT_POINT ": "
- << entry->encryption_options;
- return false;
- }
- if (options->version == 1) {
- options->use_hw_wrapped_key =
- GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT)->fs_mgr_flags.wrapped_key;
- }
- if ((options->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) &&
- !IsEmmcStorage(entry->blk_device)) {
- LOG(ERROR) << "The emmc_optimized encryption flag is only allowed on eMMC storage. Remove "
- "this flag from the device's fstab";
- return false;
- }
- return true;
-}
-
-static bool install_storage_key(const std::string& mountpoint, const EncryptionOptions& options,
- const KeyBuffer& key, EncryptionPolicy* policy) {
- KeyBuffer ephemeral_wrapped_key;
- if (options.use_hw_wrapped_key) {
- if (!exportWrappedStorageKey(key, &ephemeral_wrapped_key)) {
- LOG(ERROR) << "Failed to get ephemeral wrapped key";
- return false;
- }
- }
- return installKey(mountpoint, options, options.use_hw_wrapped_key ? ephemeral_wrapped_key : key,
- policy);
-}
-
-// Retrieve the options to use for encryption policies on adoptable storage.
-static bool get_volume_file_encryption_options(EncryptionOptions* options) {
- // If we give the empty string, libfscrypt will use the default (currently XTS)
- auto contents_mode = android::base::GetProperty("ro.crypto.volume.contents_mode", "");
- // HEH as default was always a mistake. Use the libfscrypt default (CTS)
- // for devices launching on versions above Android 10.
- auto first_api_level = GetFirstApiLevel();
- constexpr uint64_t pre_gki_level = 29;
- auto filenames_mode =
- android::base::GetProperty("ro.crypto.volume.filenames_mode",
- first_api_level > pre_gki_level ? "" : "aes-256-heh");
- auto options_string = android::base::GetProperty("ro.crypto.volume.options",
- contents_mode + ":" + filenames_mode);
- if (!ParseOptionsForApiLevel(first_api_level, options_string, options)) {
- LOG(ERROR) << "Unable to parse volume encryption options: " << options_string;
- return false;
- }
- if (options->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) {
- LOG(ERROR) << "The emmc_optimized encryption flag is only allowed on eMMC storage. Remove "
- "this flag from ro.crypto.volume.options";
- return false;
- }
- return true;
-}
-
-bool is_metadata_wrapped_key_supported() {
- if (fstab_default.empty()) {
- if (!ReadDefaultFstab(&fstab_default)) {
- PLOG(ERROR) << "Failed to open default fstab";
- return false;
- }
- }
- return GetEntryForMountPoint(&fstab_default, METADATA_MNT_POINT)->fs_mgr_flags.wrapped_key;
-}
-
-static bool read_and_install_user_ce_key(userid_t user_id,
- const ::KeyAuthentication& auth) {
- if (s_ce_policies.count(user_id) != 0) return true;
- EncryptionOptions options;
- if (!get_data_file_encryption_options(&options)) return false;
- KeyBuffer ce_key;
- if (!read_and_fixate_user_ce_key(user_id, auth, &ce_key)) return false;
- EncryptionPolicy ce_policy;
- if (!install_storage_key(DATA_MNT_POINT, options, ce_key, &ce_policy)) return false;
- s_ce_policies[user_id] = ce_policy;
- LOG(INFO) << "Installed ce key for user " << user_id;
- return true;
-}
-
-static bool prepare_dir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid) {
- LOG(INFO) << "Preparing: " << dir;
- if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
- PLOG(ERROR) << "Failed to prepare " << dir;
- return false;
- }
- return true;
-}
-
-static bool destroy_dir(const std::string& dir) {
- LOG(INFO) << "Destroying: " << dir;
- if (rmdir(dir.c_str()) != 0 && errno != ENOENT) {
- PLOG(ERROR) << "Failed to destroy " << dir;
- return false;
- }
- return true;
-}
-
-// NB this assumes that there is only one thread listening for crypt commands, because
-// it creates keys in a fixed location.
-static bool create_and_install_user_keys(userid_t user_id, bool create_ephemeral) {
- LOG(INFO) << "fscrypt::create_and_install_user_keys";
- EncryptionOptions options;
- if (!get_data_file_encryption_options(&options)) return false;
- KeyBuffer de_key, ce_key;
- if (!generateStorageKey(makeGen(options), &de_key)) return false;
- if (!generateStorageKey(makeGen(options), &ce_key)) return false;
- if (create_ephemeral) {
- // If the key should be created as ephemeral, don't store it.
- s_ephemeral_users.insert(user_id);
- } else {
- auto const directory_path = get_ce_key_directory_path(user_id);
- if (!prepare_dir(directory_path, 0700, AID_ROOT, AID_ROOT)) return false;
- auto const paths = get_ce_key_paths(directory_path);
- std::string ce_key_path;
- if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
- if (!::storeKeyAtomically(ce_key_path, user_key_temp, kEmptyAuthentication,
- ce_key))
- return false;
- fixate_user_ce_key(directory_path, ce_key_path, paths);
- // Write DE key second; once this is written, all is good.
- if (!::storeKeyAtomically(get_de_key_path(user_id), user_key_temp,
- kEmptyAuthentication, de_key))
- return false;
- }
- EncryptionPolicy de_policy;
- if (!install_storage_key(DATA_MNT_POINT, options, de_key, &de_policy)) return false;
- s_de_policies[user_id] = de_policy;
- LOG(INFO) << "fscrypt::added de_policy";
- EncryptionPolicy ce_policy;
- if (!install_storage_key(DATA_MNT_POINT, options, ce_key, &ce_policy)) return false;
- s_ce_policies[user_id] = ce_policy;
- LOG(INFO) << "Created keys for user " << user_id;
- return true;
-}
-
-bool lookup_policy(const std::map<userid_t, EncryptionPolicy>& key_map, userid_t user_id,
- EncryptionPolicy* policy) {
- auto refi = key_map.find(user_id);
- if (refi == key_map.end()) {
- LOG(ERROR) << "Cannot find key for " << user_id;
- return false;
- }
- *policy = refi->second;
- return true;
-}
-
-static bool is_numeric(const char* name) {
- for (const char* p = name; *p != '\0'; p++) {
- if (!isdigit(*p)) return false;
- }
- return true;
-}
-
-static bool load_all_de_keys() {
- LOG(INFO) << "fscrypt::load_all_de_keys";
- EncryptionOptions options;
- if (!get_data_file_encryption_options(&options)) return false;
- auto de_dir = user_key_dir + "/de";
- auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(de_dir.c_str()), closedir);
- if (!dirp) {
- PLOG(ERROR) << "Unable to read de key directory";
- return false;
- }
- for (;;) {
- errno = 0;
- auto entry = readdir(dirp.get());
- if (!entry) {
- if (errno) {
- PLOG(ERROR) << "Unable to read de key directory";
- return false;
- }
- break;
- }
- if (entry->d_type != DT_DIR || !is_numeric(entry->d_name)) {
- LOG(INFO) << "Skipping non-de-key " << entry->d_name;
- continue;
- }
- userid_t user_id = std::stoi(entry->d_name);
- auto key_path = de_dir + "/" + entry->d_name;
- KeyBuffer de_key;
- if (!retrieveKey(key_path, kEmptyAuthentication, &de_key, true)) return false;
- EncryptionPolicy de_policy;
- if (!install_storage_key(DATA_MNT_POINT, options, de_key, &de_policy)) return false;
- auto ret = s_de_policies.insert({user_id, de_policy});
- LOG(INFO) << "fscrypt::load_all_de_keys::s_de_policies::size::" << s_de_policies.size();
- if (!ret.second && ret.first->second != de_policy) {
- LOG(INFO) << "DE policy for user" << user_id << " changed";
- return false;
- }
- LOG(INFO) << "Installed de key for user " << user_id;
- std::string user_prop = "twrp.user." + std::to_string(user_id) + ".decrypt";
- property_set(user_prop.c_str(), "0");
- }
- // fscrypt:TODO: go through all DE directories, ensure that all user dirs have the
- // correct policy set on them, and that no rogue ones exist.
- return true;
-}
-
-// Attempt to reinstall CE keys for users that we think are unlocked.
-static bool try_reload_ce_keys() {
- for (const auto& it : s_ce_policies) {
- if (!::reloadKeyFromSessionKeyring(DATA_MNT_POINT, it.second)) {
- LOG(ERROR) << "Failed to load CE key from session keyring for user " << it.first;
- return false;
- }
- }
- return true;
-}
-
-bool fscrypt_initialize_systemwide_keys() {
- LOG(INFO) << "fscrypt_initialize_systemwide_keys";
-
- EncryptionOptions options;
- if (!get_data_file_encryption_options(&options)) return false;
-
- KeyBuffer device_key;
- if (!retrieveOrGenerateKey(device_key_path, device_key_temp, kEmptyAuthentication,
- makeGen(options), &device_key))
- return false;
-
- EncryptionPolicy device_policy;
- if (!install_storage_key(DATA_MNT_POINT, options, device_key, &device_policy)) return false;
-
- std::string options_string;
- if (!OptionsToString(device_policy.options, &options_string)) {
- LOG(ERROR) << "Unable to serialize options";
- return false;
- }
- std::string options_filename = std::string(DATA_MNT_POINT) + fscrypt_key_mode;
- if (!::writeStringToFile(options_string, options_filename)) return false;
-
- std::string ref_filename = std::string(DATA_MNT_POINT) + fscrypt_key_ref;
- de_key_raw_ref = device_policy.key_raw_ref;
- if (!::writeStringToFile(device_policy.key_raw_ref, ref_filename)) return false;
- LOG(INFO) << "Wrote system DE key reference to:" << ref_filename;
-
- KeyBuffer per_boot_key;
- if (!generateStorageKey(makeGen(options), &per_boot_key)) return false;
- EncryptionPolicy per_boot_policy;
- if (!install_storage_key(DATA_MNT_POINT, options, per_boot_key, &per_boot_policy)) return false;
- std::string per_boot_ref_filename = std::string("/data") + fscrypt_key_per_boot_ref;
- if (!::writeStringToFile(per_boot_policy.key_raw_ref, per_boot_ref_filename))
- return false;
- LOG(INFO) << "Wrote per boot key reference to:" << per_boot_ref_filename;
-
- if (!::FsyncDirectory(device_key_dir)) return false;
- return true;
-}
-
-bool fscrypt_init_user0() {
- if (fstab_default.empty()) {
- if (!ReadDefaultFstab(&fstab_default)) {
- PLOG(ERROR) << "Failed to open default fstab";
- return -1;
- }
- }
- LOG(INFO) << "fscrypt_init_user0";
- if (fscrypt_is_native()) {
- if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false;
- if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false;
- if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false;
- if (!::pathExists(get_de_key_path(0))) {
- if (!create_and_install_user_keys(0, false)) return false;
- }
- // TODO: switch to loading only DE_0 here once framework makes
- // explicit calls to install DE keys for secondary users
- if (!load_all_de_keys()) return false;
- }
- // We can only safely prepare DE storage here, since CE keys are probably
- // entangled with user credentials. The framework will always prepare CE
- // storage once CE keys are installed.
- LOG(INFO) << "attempting fscrypt_prepare_user_storage";
- if (!fscrypt_prepare_user_storage("", 0, 0, android::os::IVold::STORAGE_FLAG_DE)) {
- LOG(ERROR) << "Failed to prepare user 0 storage";
- return false;
- }
-
- // If this is a non-FBE device that recently left an emulated mode,
- // restore user data directories to known-good state.
- if (!fscrypt_is_native() && !fscrypt_is_emulated()) {
- LOG(INFO) << "unlocking data media";
- fscrypt_unlock_user_key(0, 0, "!", "!");
- }
-
- // In some scenarios (e.g. userspace reboot) we might unmount userdata
- // without doing a hard reboot. If CE keys were stored in fs keyring then
- // they will be lost after unmount. Attempt to re-install them.
- if (fscrypt_is_native() && ::isFsKeyringSupported()) {
- LOG(INFO) << "reloading ce keys";
- if (!try_reload_ce_keys()) return false;
- }
-
- return true;
-}
-
-bool fscrypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
- LOG(INFO) << "fscrypt_vold_create_user_key for " << user_id << " serial " << serial;
- if (!fscrypt_is_native()) {
- return true;
- }
- // FIXME test for existence of key that is not loaded yet
- if (s_ce_policies.count(user_id) != 0) {
- LOG(ERROR) << "Already exists, can't fscrypt_vold_create_user_key for " << user_id
- << " serial " << serial;
- // FIXME should we fail the command?
- return true;
- }
- if (!create_and_install_user_keys(user_id, ephemeral)) {
- return false;
- }
- return true;
-}
-
-// "Lock" all encrypted directories whose key has been removed. This is needed
-// in the case where the keys are being put in the session keyring (rather in
-// the newer filesystem-level keyrings), because removing a key from the session
-// keyring doesn't affect inodes in the kernel's inode cache whose per-file key
-// was already set up. So to remove the per-file keys and make the files
-// "appear encrypted", these inodes must be evicted.
-//
-// To do this, sync() to clean all dirty inodes, then drop all reclaimable slab
-// objects systemwide. This is overkill, but it's the best available method
-// currently. Don't use drop_caches mode "3" because that also evicts pagecache
-// for in-use files; all files relevant here are already closed and sync'ed.
-static void drop_caches_if_needed() {
- if (::isFsKeyringSupported()) {
- return;
- }
- sync();
- if (!writeStringToFile("2", "/proc/sys/vm/drop_caches")) {
- PLOG(ERROR) << "Failed to drop caches during key eviction";
- }
-}
-
-static bool evict_ce_key(userid_t user_id) {
- bool success = true;
- EncryptionPolicy policy;
- // If we haven't loaded the CE key, no need to evict it.
- if (lookup_policy(s_ce_policies, user_id, &policy)) {
- success &= ::evictKey(DATA_MNT_POINT, policy);
- drop_caches_if_needed();
- }
- s_ce_policies.erase(user_id);
- return success;
-}
-
-bool fscrypt_destroy_user_key(userid_t user_id) {
- LOG(INFO) << "fscrypt_destroy_user_key(" << user_id << ")";
- if (!fscrypt_is_native()) {
- return true;
- }
- bool success = true;
- success &= evict_ce_key(user_id);
- EncryptionPolicy de_policy;
- success &= lookup_policy(s_de_policies, user_id, &de_policy) &&
- ::evictKey(DATA_MNT_POINT, de_policy);
- s_de_policies.erase(user_id);
- auto it = s_ephemeral_users.find(user_id);
- if (it != s_ephemeral_users.end()) {
- s_ephemeral_users.erase(it);
- } else {
- for (auto const path : get_ce_key_paths(get_ce_key_directory_path(user_id))) {
- success &= ::destroyKey(path);
- }
- auto de_key_path = get_de_key_path(user_id);
- if (::pathExists(de_key_path)) {
- success &= ::destroyKey(de_key_path);
- } else {
- LOG(INFO) << "Not present so not erasing: " << de_key_path;
- }
- }
- return success;
-}
-
-static bool emulated_lock(const std::string& path) {
- if (chmod(path.c_str(), 0000) != 0) {
- PLOG(ERROR) << "Failed to chmod " << path;
- return false;
- }
-#if EMULATED_USES_SELINUX
- if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
- PLOG(WARNING) << "Failed to setfilecon " << path;
- return false;
- }
-#endif
- return true;
-}
-
-static bool emulated_unlock(const std::string& path, mode_t mode) {
- if (chmod(path.c_str(), mode) != 0) {
- PLOG(ERROR) << "Failed to chmod " << path;
- // FIXME temporary workaround for b/26713622
- if (fscrypt_is_emulated()) return false;
- }
-#if EMULATED_USES_SELINUX
- if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
- PLOG(WARNING) << "Failed to restorecon " << path;
- // FIXME temporary workaround for b/26713622
- if (fscrypt_is_emulated()) return false;
- }
-#endif
- return true;
-}
-
-static bool parse_hex(const std::string& hex, std::string* result) {
- if (hex == "!") {
- *result = "";
- return true;
- }
- if (::HexToStr(hex, *result) != 0) {
- LOG(ERROR) << "Invalid FBE hex string"; // Don't log the string for security reasons
- return false;
- }
- return true;
-}
-
-static std::optional<::KeyAuthentication> authentication_from_hex(
- const std::string& token_hex, const std::string& secret_hex) {
- std::string token, secret;
- if (!parse_hex(token_hex, &token)) return std::optional<::KeyAuthentication>();
- if (!parse_hex(secret_hex, &secret)) return std::optional<::KeyAuthentication>();
- if (secret.empty()) {
- return kEmptyAuthentication;
- } else {
- return ::KeyAuthentication(token, secret);
- }
-}
-
-static std::string volkey_path(const std::string& misc_path, const std::string& volume_uuid) {
- return misc_path + "/vold/volume_keys/" + volume_uuid + "/default";
-}
-
-static std::string volume_secdiscardable_path(const std::string& volume_uuid) {
- return systemwide_volume_key_dir + "/" + volume_uuid + "/secdiscardable";
-}
-
-static bool read_or_create_volkey(const std::string& misc_path, const std::string& volume_uuid,
- EncryptionPolicy* policy) {
- auto secdiscardable_path = volume_secdiscardable_path(volume_uuid);
- std::string secdiscardable_hash;
- if (::pathExists(secdiscardable_path)) {
- if (!readSecdiscardable(secdiscardable_path, &secdiscardable_hash))
- return false;
- } else {
- if (fs_mkdirs(secdiscardable_path.c_str(), 0700) != 0) {
- PLOG(ERROR) << "Creating directories for: " << secdiscardable_path;
- return false;
- }
- if (!::createSecdiscardable(secdiscardable_path, &secdiscardable_hash))
- return false;
- }
- auto key_path = volkey_path(misc_path, volume_uuid);
- if (fs_mkdirs(key_path.c_str(), 0700) != 0) {
- PLOG(ERROR) << "Creating directories for: " << key_path;
- return false;
- }
- ::KeyAuthentication auth("", secdiscardable_hash);
-
- EncryptionOptions options;
- if (!get_volume_file_encryption_options(&options)) return false;
- KeyBuffer key;
- if (!retrieveOrGenerateKey(key_path, key_path + "_tmp", auth, makeGen(options), &key))
- return false;
- if (!install_storage_key(BuildDataPath(volume_uuid), options, key, policy)) return false;
- return true;
-}
-
-static bool destroy_volkey(const std::string& misc_path, const std::string& volume_uuid) {
- auto path = volkey_path(misc_path, volume_uuid);
- if (!::pathExists(path)) return true;
- return ::destroyKey(path);
-}
-
-static bool fscrypt_rewrap_user_key(userid_t user_id, int serial,
- const ::KeyAuthentication& retrieve_auth,
- const ::KeyAuthentication& store_auth) {
- if (s_ephemeral_users.count(user_id) != 0) return true;
- auto const directory_path = get_ce_key_directory_path(user_id);
- KeyBuffer ce_key;
- std::string ce_key_current_path = get_ce_key_current_path(directory_path);
- if (retrieveKey(ce_key_current_path, retrieve_auth, &ce_key, true)) {
- LOG(INFO) << "Successfully retrieved key";
- // TODO(147732812): Remove this once Locksettingservice is fixed.
- // Currently it calls fscrypt_clear_user_key_auth with a secret when lockscreen is
- // changed from swipe to none or vice-versa
- } else if (retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key, true)) {
- LOG(INFO) << "Successfully retrieved key with empty auth";
- } else {
- LOG(ERROR) << "Failed to retrieve key for user " << user_id;
- return false;
- }
- auto const paths = get_ce_key_paths(directory_path);
- std::string ce_key_path;
- if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
- if (!::storeKeyAtomically(ce_key_path, user_key_temp, store_auth, ce_key))
- return false;
- if (!::FsyncDirectory(directory_path)) return false;
- return true;
-}
-
-bool fscrypt_add_user_key_auth(userid_t user_id, int serial, const std::string& token_hex,
- const std::string& secret_hex) {
- LOG(INFO) << "fscrypt_add_user_key_auth " << user_id << " serial=" << serial
- << " token_present=" << (token_hex != "!");
- if (!fscrypt_is_native()) return true;
- auto auth = authentication_from_hex(token_hex, secret_hex);
- if (!auth) return false;
- return fscrypt_rewrap_user_key(user_id, serial, kEmptyAuthentication, *auth);
-}
-
-bool fscrypt_clear_user_key_auth(userid_t user_id, int serial, const std::string& token_hex,
- const std::string& secret_hex) {
- LOG(INFO) << "fscrypt_clear_user_key_auth " << user_id << " serial=" << serial
- << " token_present=" << (token_hex != "!");
- if (!fscrypt_is_native()) return true;
- auto auth = authentication_from_hex(token_hex, secret_hex);
- if (!auth) return false;
- return fscrypt_rewrap_user_key(user_id, serial, *auth, kEmptyAuthentication);
-}
-
-bool fscrypt_fixate_newest_user_key_auth(userid_t user_id) {
- LOG(INFO) << "fscrypt_fixate_newest_user_key_auth " << user_id;
- if (!fscrypt_is_native()) return true;
- if (s_ephemeral_users.count(user_id) != 0) return true;
- auto const directory_path = get_ce_key_directory_path(user_id);
- auto const paths = get_ce_key_paths(directory_path);
- if (paths.empty()) {
- LOG(ERROR) << "No ce keys present, cannot fixate for user " << user_id;
- return false;
- }
- fixate_user_ce_key(directory_path, paths[0], paths);
- return true;
-}
-
-// TODO: rename to 'install' for consistency, and take flags to know which keys to install
-bool fscrypt_unlock_user_key(userid_t user_id, int serial, const std::string& token_hex,
- const std::string& secret_hex) {
- LOG(INFO) << "fscrypt_unlock_user_key " << user_id << " serial=" << serial
- << " token_present=" << (token_hex != "!");
- if (fscrypt_is_native()) {
- if (s_ce_policies.count(user_id) != 0) {
- LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id;
- return true;
- }
- auto auth = authentication_from_hex(token_hex, secret_hex);
- if (!auth) return false;
- if (!read_and_install_user_ce_key(user_id, *auth)) {
- LOG(ERROR) << "Couldn't read key for " << user_id;
- return false;
- }
- } else {
- // When in emulation mode, we just use chmod. However, we also
- // unlock directories when not in emulation mode, to bring devices
- // back into a known-good state.
- if (!emulated_unlock(::BuildDataSystemCePath(user_id), 0771) ||
- !emulated_unlock(::BuildDataMiscCePath(user_id), 01771) ||
- !emulated_unlock(::BuildDataMediaCePath("", user_id), 0770) ||
- !emulated_unlock(::BuildDataUserCePath("", user_id), 0771)) {
- LOG(ERROR) << "Failed to unlock user " << user_id;
- return false;
- }
- }
- return true;
-}
-
-// TODO: rename to 'evict' for consistency
-bool fscrypt_lock_user_key(userid_t user_id) {
- LOG(INFO) << "fscrypt_lock_user_key " << user_id;
- if (fscrypt_is_native()) {
- return evict_ce_key(user_id);
- } else if (fscrypt_is_emulated()) {
- // When in emulation mode, we just use chmod
- if (!emulated_lock(::BuildDataSystemCePath(user_id)) ||
- !emulated_lock(::BuildDataMiscCePath(user_id)) ||
- !emulated_lock(::BuildDataMediaCePath("", user_id)) ||
- !emulated_lock(::BuildDataUserCePath("", user_id))) {
- LOG(ERROR) << "Failed to lock user " << user_id;
- return false;
- }
- }
-
- return true;
-}
-
-static bool prepare_subdirs(const std::string& action, const std::string& volume_uuid,
- userid_t user_id, int flags) {
- if (0 != ::ForkExecvp(
- std::vector<std::string>{prepare_subdirs_path, action, volume_uuid,
- std::to_string(user_id), std::to_string(flags)})) {
- LOG(ERROR) << "vold_prepare_subdirs failed";
- return false;
- }
- return true;
-}
-
-bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial,
- int flags) {
- LOG(INFO) << "fscrypt_prepare_user_storage for volume " << escape_empty(volume_uuid)
- << ", user " << user_id << ", serial " << serial << ", flags " << flags;
-
- if (flags & android::os::IVold::STORAGE_FLAG_DE) {
- // DE_sys key
- auto system_legacy_path = ::BuildDataSystemLegacyPath(user_id);
- auto misc_legacy_path = ::BuildDataMiscLegacyPath(user_id);
- auto profiles_de_path = ::BuildDataProfilesDePath(user_id);
-
- // DE_n key
- auto system_de_path = ::BuildDataSystemDePath(user_id);
- auto misc_de_path = ::BuildDataMiscDePath(user_id);
- auto vendor_de_path = ::BuildDataVendorDePath(user_id);
- auto user_de_path = ::BuildDataUserDePath(volume_uuid, user_id);
-
- if (volume_uuid.empty()) {
- if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
-#if MANAGE_MISC_DIRS
- if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM),
- multiuser_get_uid(user_id, AID_EVERYBODY)))
- return false;
-#endif
- if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
-
- if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
- if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false;
- if (!prepare_dir(vendor_de_path, 0771, AID_ROOT, AID_ROOT)) return false;
- }
- if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
- if (fscrypt_is_native()) {
- EncryptionPolicy de_policy;
- if (volume_uuid.empty()) {
- if (!lookup_policy(s_de_policies, user_id, &de_policy)) return false;
- if (!EnsurePolicy(de_policy, system_de_path))
- LOG(INFO) << "EnsurePolicy returned false for " << system_de_path;
- if (!EnsurePolicy(de_policy, misc_de_path))
- LOG(INFO) << "EnsurePolicy returned false for " << misc_de_path;
- if (!EnsurePolicy(de_policy, vendor_de_path))
- LOG(INFO) << "EnsurePolicy returned false for " << vendor_de_path;
- } else {
- if (!read_or_create_volkey(misc_de_path, volume_uuid, &de_policy)) return false;
- }
- if (!EnsurePolicy(de_policy, user_de_path))
- LOG(INFO) << "EnsurePolicy returned false for " << user_de_path;
-
- }
- }
-
- if (flags & android::os::IVold::STORAGE_FLAG_CE) {
- // CE_n key
- auto system_ce_path = ::BuildDataSystemCePath(user_id);
- auto misc_ce_path = ::BuildDataMiscCePath(user_id);
- auto vendor_ce_path = ::BuildDataVendorCePath(user_id);
- auto media_ce_path = ::BuildDataMediaCePath(volume_uuid, user_id);
- auto user_ce_path = ::BuildDataUserCePath(volume_uuid, user_id);
-
- if (volume_uuid.empty()) {
- if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
- if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false;
- if (!prepare_dir(vendor_ce_path, 0771, AID_ROOT, AID_ROOT)) return false;
- }
- if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
-
- if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
-
- if (fscrypt_is_native()) {
- EncryptionPolicy ce_policy;
- if (volume_uuid.empty()) {
- if (!lookup_policy(s_ce_policies, user_id, &ce_policy)) return false;
- if (!EnsurePolicy(ce_policy, system_ce_path))
- LOG(INFO) << "EnsurePolicy returned false for " << system_ce_path;
- if (!EnsurePolicy(ce_policy, misc_ce_path))
- LOG(INFO) << "EnsurePolicy returned false for " << misc_ce_path;
- if (!EnsurePolicy(ce_policy, vendor_ce_path))
- LOG(INFO) << "EnsurePolicy returned false for " << vendor_ce_path;
- } else {
- if (!read_or_create_volkey(misc_ce_path, volume_uuid, &ce_policy)) return false;
- }
- if (!EnsurePolicy(ce_policy, media_ce_path))
- LOG(INFO) << "EnsurePolicy returned false for " << media_ce_path;
- if (!EnsurePolicy(ce_policy, user_ce_path))
- LOG(INFO) << "EnsurePolicy returned false for " << user_ce_path;
- }
-
- if (volume_uuid.empty()) {
- // Now that credentials have been installed, we can run restorecon
- // over these paths
- // NOTE: these paths need to be kept in sync with libselinux
- ::RestoreconRecursive(system_ce_path);
- ::RestoreconRecursive(vendor_ce_path);
- ::RestoreconRecursive(misc_ce_path);
- }
- }
- if (!prepare_subdirs("prepare", volume_uuid, user_id, flags)) return false;
-
- return true;
-}
-
-bool fscrypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_id, int flags) {
- LOG(INFO) << "fscrypt_destroy_user_storage for volume " << escape_empty(volume_uuid)
- << ", user " << user_id << ", flags " << flags;
- bool res = true;
-
- res &= prepare_subdirs("destroy", volume_uuid, user_id, flags);
-
- if (flags & android::os::IVold::STORAGE_FLAG_CE) {
- // CE_n key
- auto system_ce_path = ::BuildDataSystemCePath(user_id);
- auto misc_ce_path = ::BuildDataMiscCePath(user_id);
- auto vendor_ce_path = ::BuildDataVendorCePath(user_id);
- auto media_ce_path = ::BuildDataMediaCePath(volume_uuid, user_id);
- auto user_ce_path = ::BuildDataUserCePath(volume_uuid, user_id);
-
- res &= destroy_dir(media_ce_path);
- res &= destroy_dir(user_ce_path);
- if (volume_uuid.empty()) {
- res &= destroy_dir(system_ce_path);
- res &= destroy_dir(misc_ce_path);
- res &= destroy_dir(vendor_ce_path);
- } else {
- if (fscrypt_is_native()) {
- res &= destroy_volkey(misc_ce_path, volume_uuid);
- }
- }
- }
-
- if (flags & android::os::IVold::STORAGE_FLAG_DE) {
- // DE_sys key
- auto system_legacy_path = ::BuildDataSystemLegacyPath(user_id);
- auto misc_legacy_path = ::BuildDataMiscLegacyPath(user_id);
- auto profiles_de_path = ::BuildDataProfilesDePath(user_id);
-
- // DE_n key
- auto system_de_path = ::BuildDataSystemDePath(user_id);
- auto misc_de_path = ::BuildDataMiscDePath(user_id);
- auto vendor_de_path = ::BuildDataVendorDePath(user_id);
- auto user_de_path = ::BuildDataUserDePath(volume_uuid, user_id);
-
- res &= destroy_dir(user_de_path);
- if (volume_uuid.empty()) {
- res &= destroy_dir(system_legacy_path);
-#if MANAGE_MISC_DIRS
- res &= destroy_dir(misc_legacy_path);
-#endif
- res &= destroy_dir(profiles_de_path);
- res &= destroy_dir(system_de_path);
- res &= destroy_dir(misc_de_path);
- res &= destroy_dir(vendor_de_path);
- } else {
- if (fscrypt_is_native()) {
- res &= destroy_volkey(misc_de_path, volume_uuid);
- }
- }
- }
-
- return res;
-}
-
-static bool destroy_volume_keys(const std::string& directory_path, const std::string& volume_uuid) {
- auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(directory_path.c_str()), closedir);
- if (!dirp) {
- PLOG(ERROR) << "Unable to open directory: " + directory_path;
- return false;
- }
- bool res = true;
- for (;;) {
- errno = 0;
- auto const entry = readdir(dirp.get());
- if (!entry) {
- if (errno) {
- PLOG(ERROR) << "Unable to read directory: " + directory_path;
- return false;
- }
- break;
- }
- if (entry->d_type != DT_DIR || entry->d_name[0] == '.') {
- LOG(INFO) << "Skipping non-user " << entry->d_name;
- continue;
- }
- res &= destroy_volkey(directory_path + "/" + entry->d_name, volume_uuid);
- }
- return res;
-}
-
-bool fscrypt_destroy_volume_keys(const std::string& volume_uuid) {
- bool res = true;
- LOG(INFO) << "fscrypt_destroy_volume_keys for volume " << escape_empty(volume_uuid);
- auto secdiscardable_path = volume_secdiscardable_path(volume_uuid);
- res &= ::runSecdiscardSingle(secdiscardable_path);
- res &= destroy_volume_keys("/data/misc_ce", volume_uuid);
- res &= destroy_volume_keys("/data/misc_de", volume_uuid);
- return res;
-}
-
-bool lookup_key_ref(const std::map<userid_t, android::fscrypt::EncryptionPolicy>& key_map, userid_t user_id,
- std::string* raw_ref) {
- auto refi = key_map.find(user_id);
- if (refi == key_map.end()) {
- LOG(ERROR) << "Cannot find key for " << user_id;
- return false;
- }
- *raw_ref = refi->second.key_raw_ref;
- return true;
-}
diff --git a/crypto/fscrypt/FsCrypt.h b/crypto/fscrypt/FsCrypt.h
deleted file mode 100755
index 0cb38c1..0000000
--- a/crypto/fscrypt/FsCrypt.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2015 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 <map>
-#include <string>
-
-#include <fscrypt/fscrypt.h>
-#include <cutils/multiuser.h>
-
-using namespace android::fscrypt;
-
-bool fscrypt_initialize_systemwide_keys();
-
-bool fscrypt_init_user0();
-bool fscrypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral);
-bool fscrypt_destroy_user_key(userid_t user_id);
-bool fscrypt_add_user_key_auth(userid_t user_id, int serial, const std::string& token,
- const std::string& secret);
-bool fscrypt_clear_user_key_auth(userid_t user_id, int serial, const std::string& token,
- const std::string& secret);
-bool fscrypt_fixate_newest_user_key_auth(userid_t user_id);
-
-bool fscrypt_unlock_user_key(userid_t user_id, int serial, const std::string& token,
- const std::string& secret);
-bool fscrypt_lock_user_key(userid_t user_id);
-
-bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial,
- int flags);
-bool is_metadata_wrapped_key_supported();
-bool fscrypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_id, int flags);
-
-bool fscrypt_destroy_volume_keys(const std::string& volume_uuid);
-
-bool lookup_key_ref(const std::map<userid_t, android::fscrypt::EncryptionPolicy>& key_map, userid_t user_id,
- std::string* raw_ref);
-bool lookup_policy(const std::map<userid_t, EncryptionPolicy>& key_map, userid_t user_id,
- EncryptionPolicy* policy);
\ No newline at end of file
diff --git a/crypto/fscrypt/HashPassword.cpp b/crypto/fscrypt/HashPassword.cpp
deleted file mode 100644
index 07ecb1f..0000000
--- a/crypto/fscrypt/HashPassword.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2016 Team Win Recovery 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 computes the "secret" used by Android as one of the parameters
- * to decrypt File Based Encryption. The secret is prefixed with
- * "Android FBE credential hash" padded with 0s to 128 bytes then the
- * user's password is appended to the end of the 128 bytes. This string
- * is then hashed with sha512 and the sha512 value is then converted to
- * hex with upper-case characters.
- */
-
-#include <stdio.h>
-#include <string>
-#include <stdlib.h>
-#include <openssl/sha.h>
-#include <openssl/hmac.h>
-
-#include "HashPassword.h"
-
-#define PASS_PADDING_SIZE 128
-#define SHA512_HEX_SIZE SHA512_DIGEST_LENGTH * 2
-#define SHA256_HEX_SIZE SHA256_DIGEST_LENGTH * 2
-
-void* PersonalizedHashBinary(const char* prefix, const char* key, const size_t key_size) {
- size_t size = PASS_PADDING_SIZE + key_size;
- unsigned char* buffer = (unsigned char*)calloc(1, size);
- if (!buffer) return NULL; // failed to malloc
- memcpy((void*)buffer, (void*)prefix, strlen(prefix));
- unsigned char* ptr = buffer + PASS_PADDING_SIZE;
- memcpy((void*)ptr, key, key_size);
- unsigned char hash[SHA512_DIGEST_LENGTH];
- SHA512_CTX sha512;
- SHA512_Init(&sha512);
- SHA512_Update(&sha512, buffer, size);
- SHA512_Final(hash, &sha512);
- free(buffer);
- void* ret = malloc(SHA512_DIGEST_LENGTH);
- if (!ret) return NULL; // failed to malloc
- memcpy(ret, (void*)&hash[0], SHA512_DIGEST_LENGTH);
- return ret;
-}
-
-std::string PersonalizedHash(const char* prefix, const char* key, const size_t key_size) {
- size_t size = PASS_PADDING_SIZE + key_size;
- unsigned char* buffer = (unsigned char*)calloc(1, size);
- if (!buffer) return ""; // failed to malloc
- memcpy((void*)buffer, (void*)prefix, strlen(prefix));
- unsigned char* ptr = buffer + PASS_PADDING_SIZE;
- memcpy((void*)ptr, key, key_size);
- unsigned char hash[SHA512_DIGEST_LENGTH];
- SHA512_CTX sha512;
- SHA512_Init(&sha512);
- SHA512_Update(&sha512, buffer, size);
- SHA512_Final(hash, &sha512);
- int index = 0;
- char hex_hash[SHA512_HEX_SIZE + 1];
- for(index = 0; index < SHA512_DIGEST_LENGTH; index++)
- sprintf(hex_hash + (index * 2), "%02X", hash[index]);
- hex_hash[128] = 0;
- std::string ret = hex_hash;
- free(buffer);
- return ret;
-}
-
-std::string PersonalizedHash(const char* prefix, const std::string& Password) {
- return PersonalizedHash(prefix, Password.c_str(), Password.size());
-}
-
-std::string PersonalizedHashSP800(const char* label, const char* context, const char* key, const size_t key_size) {
- HMAC_CTX ctx;
- HMAC_CTX_init(&ctx);
- HMAC_Init_ex(&ctx, key, key_size, EVP_sha256(), NULL);
- unsigned int counter = 1;
- endianswap(&counter);
- HMAC_Update(&ctx, (const unsigned char*)&counter, 4);
- HMAC_Update(&ctx, (const unsigned char*)label, strlen(label));
- const unsigned char divider = 0;
- HMAC_Update(&ctx, ÷r, 1);
- HMAC_Update(&ctx, (const unsigned char*)context, strlen(context));
- unsigned int contextDisambiguation = strlen(context) * 8;
- endianswap(&contextDisambiguation);
- HMAC_Update(&ctx, (const unsigned char*)&contextDisambiguation, 4);
- unsigned int finalValue = 256;
- endianswap(&finalValue);
- HMAC_Update(&ctx, (const unsigned char*)&finalValue, 4);
-
- unsigned char output[SHA256_DIGEST_LENGTH];
- unsigned int out_size = 0;
- HMAC_Final(&ctx, output, &out_size);
-
- int index = 0;
- char hex_hash[SHA256_HEX_SIZE + 1];
- for(index = 0; index < SHA256_DIGEST_LENGTH; index++)
- sprintf(hex_hash + (index * 2), "%02x", output[index]);
- hex_hash[SHA256_HEX_SIZE] = 0;
- std::string ret = hex_hash;
- return ret;
-}
-
-std::string HashPassword(const std::string& Password) {
- const char* prefix = FBE_PERSONALIZATION;
- return PersonalizedHash(prefix, Password);
-}
diff --git a/crypto/fscrypt/HashPassword.h b/crypto/fscrypt/HashPassword.h
deleted file mode 100644
index 73880b1..0000000
--- a/crypto/fscrypt/HashPassword.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2016 Team Win Recovery 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 __HASH_PASSWORD_H
-#define __HASH_PASSWORD_H
-
-#include <string>
-
-#define FBE_PERSONALIZATION "Android FBE credential hash"
-#define PERSONALISATION_WEAVER_KEY "weaver-key"
-#define PERSONALISATION_WEAVER_PASSWORD "weaver-pwd"
-#define PERSONALISATION_APPLICATION_ID "application-id"
-#define PERSONALIZATION_FBE_KEY "fbe-key"
-#define PERSONALIZATION_USER_GK_AUTH "user-gk-authentication"
-#define PERSONALISATION_SECDISCARDABLE "secdiscardable-transform"
-#define PERSONALISATION_CONTEXT "android-synthetic-password-personalization-context"
-
-void* PersonalizedHashBinary(const char* prefix, const char* key, const size_t key_size);
-
-std::string PersonalizedHash(const char* prefix, const char* key, const size_t key_size);
-std::string PersonalizedHash(const char* prefix, const std::string& Password);
-std::string PersonalizedHashSP800(const char* label, const char* context, const char* key, const size_t key_size);
-std::string HashPassword(const std::string& Password);
-
-template <class T>
-void endianswap(T *objp) {
- unsigned char *memp = reinterpret_cast<unsigned char*>(objp);
- std::reverse(memp, memp + sizeof(T));
-}
-
-#endif
diff --git a/crypto/fscrypt/KeyBuffer.cpp b/crypto/fscrypt/KeyBuffer.cpp
deleted file mode 100644
index e7aede5..0000000
--- a/crypto/fscrypt/KeyBuffer.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2017 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 "KeyBuffer.h"
-
-#include <algorithm>
-#include <cstring>
-
-namespace android {
-namespace vold {
-
-KeyBuffer operator+(KeyBuffer&& lhs, const KeyBuffer& rhs) {
- std::copy(rhs.begin(), rhs.end(), std::back_inserter(lhs));
- return std::move(lhs);
-}
-
-KeyBuffer operator+(KeyBuffer&& lhs, const char* rhs) {
- std::copy(rhs, rhs + strlen(rhs), std::back_inserter(lhs));
- return std::move(lhs);
-}
-
-} // namespace vold
-} // namespace android
-
diff --git a/crypto/fscrypt/KeyBuffer.h b/crypto/fscrypt/KeyBuffer.h
deleted file mode 100644
index 2de9ac9..0000000
--- a/crypto/fscrypt/KeyBuffer.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2017 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 ANDROID_VOLD_KEYBUFFER_H
-#define ANDROID_VOLD_KEYBUFFER_H
-
-#include <cstring>
-#include <memory>
-#include <vector>
-
-
-/**
- * Variant of memset() that should never be optimized away. Borrowed from keymaster code.
- */
-#ifdef __clang__
-#define OPTNONE __attribute__((optnone))
-#else // not __clang__
-#define OPTNONE __attribute__((optimize("O0")))
-#endif // not __clang__
-inline OPTNONE void* memset_s(void* s, int c, size_t n) {
- if (!s)
- return s;
- return memset(s, c, n);
-}
-#undef OPTNONE
-
-// Allocator that delegates useful work to standard one but zeroes data before deallocating.
-class ZeroingAllocator : public std::allocator<char> {
- public:
- void deallocate(pointer p, size_type n)
- {
- memset_s(p, 0, n);
- std::allocator<char>::deallocate(p, n);
- }
-};
-
-// Char vector that zeroes memory when deallocating.
-using KeyBuffer = std::vector<char, ZeroingAllocator>;
-
-// Convenience methods to concatenate key buffers.
-KeyBuffer operator+(KeyBuffer&& lhs, const KeyBuffer& rhs);
-KeyBuffer operator+(KeyBuffer&& lhs, const char* rhs);
-
-#endif
-
diff --git a/crypto/fscrypt/KeyStorage.cpp b/crypto/fscrypt/KeyStorage.cpp
deleted file mode 100755
index 8afc579..0000000
--- a/crypto/fscrypt/KeyStorage.cpp
+++ /dev/null
@@ -1,647 +0,0 @@
-/*
- * Copyright (C) 2016 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 "KeyStorage.h"
-
-#include "Checkpoint.h"
-#include "Keymaster.h"
-#include "ScryptParameters.h"
-#include "Utils.h"
-
-#include <thread>
-#include <vector>
-
-#include <errno.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/sha.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/unique_fd.h>
-
-#include <cutils/properties.h>
-
-#include <hardware/hw_auth_token.h>
-#include <keymasterV4_1/authorization_set.h>
-#include <keymasterV4_1/keymaster_utils.h>
-
-extern "C" {
-
-#include "crypto_scrypt.h"
-}
-
-const KeyAuthentication kEmptyAuthentication{"", ""};
-
-static constexpr size_t AES_KEY_BYTES = 32;
-static constexpr size_t GCM_NONCE_BYTES = 12;
-static constexpr size_t GCM_MAC_BYTES = 16;
-static constexpr size_t SALT_BYTES = 1 << 4;
-static constexpr size_t SECDISCARDABLE_BYTES = 1 << 14;
-static constexpr size_t STRETCHED_BYTES = 1 << 6;
-
-static constexpr uint32_t AUTH_TIMEOUT = 30; // Seconds
-
-static const std::string kPkmBlob("pKMblob\x00", 8);
-
-static const char* kCurrentVersion = "1";
-static const char* kRmPath = "/system/bin/rm";
-static const char* kSecdiscardPath = "/system/bin/secdiscard";
-static const char* kStretch_none = "none";
-static const char* kStretch_nopassword = "nopassword";
-static const std::string kStretchPrefix_scrypt = "scrypt ";
-static const char* kHashPrefix_secdiscardable = "Android secdiscardable SHA512";
-static const char* kHashPrefix_keygen = "Android key wrapping key generation SHA512";
-static const char* kFn_encrypted_key = "encrypted_key";
-static const char* kFn_keymaster_key_blob = "keymaster_key_blob";
-static const char* kFn_keymaster_key_blob_upgraded = "keymaster_key_blob_upgraded";
-static const char* kFn_salt = "salt";
-static const char* kFn_secdiscardable = "secdiscardable";
-static const char* kFn_stretching = "stretching";
-static const char* kFn_version = "version";
-
-static bool checkSize(const std::string& kind, size_t actual, size_t expected) {
- if (actual != expected) {
- LOG(ERROR) << "Wrong number of bytes in " << kind << ", expected " << expected << " got "
- << actual;
- return false;
- }
- return true;
-}
-
-static void hashWithPrefix(char const* prefix, const std::string& tohash, std::string* res) {
- SHA512_CTX c;
-
- SHA512_Init(&c);
- // Personalise the hashing by introducing a fixed prefix.
- // Hashing applications should use personalization except when there is a
- // specific reason not to; see section 4.11 of https://www.schneier.com/skein1.3.pdf
- std::string hashingPrefix = prefix;
- hashingPrefix.resize(SHA512_CBLOCK);
- SHA512_Update(&c, hashingPrefix.data(), hashingPrefix.size());
- SHA512_Update(&c, tohash.data(), tohash.size());
- res->assign(SHA512_DIGEST_LENGTH, '\0');
- SHA512_Final(reinterpret_cast<uint8_t*>(&(*res)[0]), &c);
-}
-
-static bool generateKeymasterKey(Keymaster& keymaster, const KeyAuthentication& auth,
- const std::string& appId, std::string* key) {
- auto paramBuilder = km::AuthorizationSetBuilder()
- .AesEncryptionKey(AES_KEY_BYTES * 8)
- .GcmModeMinMacLen(GCM_MAC_BYTES * 8)
- .Authorization(km::TAG_APPLICATION_ID, km::support::blob2hidlVec(appId));
- if (auth.token.empty()) {
- LOG(DEBUG) << "Creating key that doesn't need auth token";
- paramBuilder.Authorization(km::TAG_NO_AUTH_REQUIRED);
- } else {
- LOG(DEBUG) << "Auth token required for key";
- if (auth.token.size() != sizeof(hw_auth_token_t)) {
- LOG(ERROR) << "Auth token should be " << sizeof(hw_auth_token_t) << " bytes, was "
- << auth.token.size() << " bytes";
- return false;
- }
- const hw_auth_token_t* at = reinterpret_cast<const hw_auth_token_t*>(auth.token.data());
- auto user_id = at->user_id; // Make a copy because at->user_id is unaligned.
- paramBuilder.Authorization(km::TAG_USER_SECURE_ID, user_id);
- paramBuilder.Authorization(km::TAG_USER_AUTH_TYPE, km::HardwareAuthenticatorType::PASSWORD);
- paramBuilder.Authorization(km::TAG_AUTH_TIMEOUT, AUTH_TIMEOUT);
- }
-
- auto paramsWithRollback = paramBuilder;
- paramsWithRollback.Authorization(km::TAG_ROLLBACK_RESISTANCE);
-
- // Generate rollback-resistant key if possible.
- return keymaster.generateKey(paramsWithRollback, key) ||
- keymaster.generateKey(paramBuilder, key);
-}
-
-bool generateWrappedStorageKey(KeyBuffer* key) {
- Keymaster keymaster;
- if (!keymaster) return false;
- std::string key_temp;
- auto paramBuilder = km::AuthorizationSetBuilder().AesEncryptionKey(AES_KEY_BYTES * 8);
- km::KeyParameter param1;
- param1.tag = static_cast<::android::hardware::keymaster::V4_0::Tag>(
- android::hardware::keymaster::V4_0::KM_TAG_FBE_ICE);
- param1.f.boolValue = true;
- paramBuilder.push_back(param1);
- if (!keymaster.generateKey(paramBuilder, &key_temp)) return false;
- *key = KeyBuffer(key_temp.size());
- memcpy(reinterpret_cast<void*>(key->data()), key_temp.c_str(), key->size());
- return true;
-}
-
-bool exportWrappedStorageKey(const KeyBuffer& kmKey, KeyBuffer* key) {
- Keymaster keymaster;
- if (!keymaster) return false;
- std::string key_temp;
-
- auto ret = keymaster.exportKey(kmKey, &key_temp);
- if (ret != km::ErrorCode::OK) {
- if (ret == km::ErrorCode::KEY_REQUIRES_UPGRADE) {
- std::string kmKeyStr(reinterpret_cast<const char*>(kmKey.data()), kmKey.size());
- std::string Keystr;
- if (!keymaster.upgradeKey(kmKeyStr, km::AuthorizationSet(), &Keystr)) return false;
- KeyBuffer upgradedKey = KeyBuffer(Keystr.size());
- memcpy(reinterpret_cast<void*>(upgradedKey.data()), Keystr.c_str(), upgradedKey.size());
- ret = keymaster.exportKey(upgradedKey, &key_temp);
- if (ret != km::ErrorCode::OK) return false;
- } else {
- return false;
- }
- } *key = KeyBuffer(key_temp.size());
- memcpy(reinterpret_cast<void*>(key->data()), key_temp.c_str(), key->size());
- return true;
-}
-
-static std::pair<km::AuthorizationSet, km::HardwareAuthToken> beginParams(
- const KeyAuthentication& auth, const std::string& appId) {
- auto paramBuilder = km::AuthorizationSetBuilder()
- .GcmModeMacLen(GCM_MAC_BYTES * 8)
- .Authorization(km::TAG_APPLICATION_ID, km::support::blob2hidlVec(appId));
- km::HardwareAuthToken authToken;
- if (!auth.token.empty()) {
- LOG(INFO) << "Supplying auth token to Keymaster";
- authToken = km::support::hidlVec2AuthToken(km::support::blob2hidlVec(auth.token));
- }
- return {paramBuilder, authToken};
-}
-
-static bool readFileToString(const std::string& filename, std::string* result) {
- if (!android::base::ReadFileToString(filename, result)) {
- PLOG(ERROR) << "Failed to read from " << filename;
- return false;
- }
- return true;
-}
-
-static bool readRandomBytesOrLog(size_t count, std::string* out) {
- auto status = ReadRandomBytes(count, *out);
- if (status != android::OK) {
- LOG(ERROR) << "Random read failed with status: " << status;
- return false;
- }
- return true;
-}
-
-bool createSecdiscardable(const std::string& filename, std::string* hash) {
- std::string secdiscardable;
- if (!readRandomBytesOrLog(SECDISCARDABLE_BYTES, &secdiscardable)) return false;
- if (!writeStringToFile(secdiscardable, filename)) return false;
- hashWithPrefix(kHashPrefix_secdiscardable, secdiscardable, hash);
- return true;
-}
-
-bool readSecdiscardable(const std::string& filename, std::string* hash) {
- std::string secdiscardable;
- if (!readFileToString(filename, &secdiscardable)) return false;
- hashWithPrefix(kHashPrefix_secdiscardable, secdiscardable, hash);
- return true;
-}
-
-static void deferedKmDeleteKey(const std::string& kmkey) {
- while (!android::base::WaitForProperty("vold.checkpoint_committed", "1")) {
- LOG(ERROR) << "Wait for boot timed out";
- }
- Keymaster keymaster;
- if (!keymaster || !keymaster.deleteKey(kmkey)) {
- LOG(ERROR) << "Defered Key deletion failed during upgrade";
- }
-}
-
-bool kmDeleteKey(Keymaster& keymaster, const std::string& kmKey) {
- bool needs_cp = cp_needsCheckpoint();
-
- if (needs_cp) {
- std::thread(deferedKmDeleteKey, kmKey).detach();
- LOG(INFO) << "Deferring Key deletion during upgrade";
- return true;
- } else {
- return keymaster.deleteKey(kmKey);
- }
-}
-
-static KeymasterOperation begin(Keymaster& keymaster, const std::string& dir,
- km::KeyPurpose purpose, const km::AuthorizationSet& keyParams,
- const km::AuthorizationSet& opParams,
- const km::HardwareAuthToken& authToken,
- km::AuthorizationSet* outParams, bool keepOld) {
- auto kmKeyPath = dir + "/" + kFn_keymaster_key_blob;
- std::string kmKey;
- if (!readFileToString(kmKeyPath, &kmKey)) return KeymasterOperation();
- // In A12 keymaster_key_blob format changed:
- // it have useless for us bytes in beginning, so remove them to correctly handle key
- if (!kmKey.compare(0, kPkmBlob.size(), kPkmBlob))
- kmKey.erase(0, kPkmBlob.size());
- km::AuthorizationSet inParams(keyParams);
- inParams.append(opParams.begin(), opParams.end());
- for (;;) {
- auto opHandle = keymaster.begin(purpose, kmKey, inParams, authToken, outParams);
- if (opHandle) {
- return opHandle;
- }
- if (opHandle.errorCode() != km::ErrorCode::KEY_REQUIRES_UPGRADE) return opHandle;
- LOG(DEBUG) << "Upgrading key: " << dir;
- std::string newKey;
- if (!keymaster.upgradeKey(kmKey, keyParams, &newKey)) return KeymasterOperation();
- auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
- if (!writeStringToFile(newKey, newKeyPath)) return KeymasterOperation();
- if (!keepOld) {
- if (rename(newKeyPath.c_str(), kmKeyPath.c_str()) != 0) {
- PLOG(ERROR) << "Unable to move upgraded key to location: " << kmKeyPath;
- return KeymasterOperation();
- }
- if (!::FsyncDirectory(dir)) {
- LOG(ERROR) << "Key dir sync failed: " << dir;
- return KeymasterOperation();
- }
- if (!kmDeleteKey(keymaster, kmKey)) {
- LOG(ERROR) << "Key deletion failed during upgrade, continuing anyway: " << dir;
- }
- }
- kmKey = newKey;
- LOG(INFO) << "Key upgraded: " << dir;
- }
-}
-
-static bool encryptWithKeymasterKey(Keymaster& keymaster, const std::string& dir,
- const km::AuthorizationSet& keyParams,
- const km::HardwareAuthToken& authToken, const KeyBuffer& message,
- std::string* ciphertext, bool keepOld) {
- km::AuthorizationSet opParams;
- km::AuthorizationSet outParams;
- auto opHandle = begin(keymaster, dir, km::KeyPurpose::ENCRYPT, keyParams, opParams, authToken,
- &outParams, keepOld);
- if (!opHandle) return false;
- auto nonceBlob = outParams.GetTagValue(km::TAG_NONCE);
- if (!nonceBlob.isOk()) {
- LOG(ERROR) << "GCM encryption but no nonce generated";
- return false;
- }
- // nonceBlob here is just a pointer into existing data, must not be freed
- std::string nonce(reinterpret_cast<const char*>(&nonceBlob.value()[0]),
- nonceBlob.value().size());
- if (!checkSize("nonce", nonce.size(), GCM_NONCE_BYTES)) return false;
- std::string body;
- if (!opHandle.updateCompletely(message, &body)) return false;
-
- std::string mac;
- if (!opHandle.finish(&mac)) return false;
- if (!checkSize("mac", mac.size(), GCM_MAC_BYTES)) return false;
- *ciphertext = nonce + body + mac;
- return true;
-}
-
-static bool decryptWithKeymasterKey(Keymaster& keymaster, const std::string& dir,
- const km::AuthorizationSet& keyParams,
- const km::HardwareAuthToken& authToken,
- const std::string& ciphertext, KeyBuffer* message,
- bool keepOld) {
- auto nonce = ciphertext.substr(0, GCM_NONCE_BYTES);
- auto bodyAndMac = ciphertext.substr(GCM_NONCE_BYTES);
- auto opParams = km::AuthorizationSetBuilder().Authorization(km::TAG_NONCE,
- km::support::blob2hidlVec(nonce));
- auto opHandle = begin(keymaster, dir, km::KeyPurpose::DECRYPT, keyParams, opParams, authToken,
- nullptr, keepOld);
- if (!opHandle) return false;
- if (!opHandle.updateCompletely(bodyAndMac, message)) return false;
- if (!opHandle.finish(nullptr)) return false;
- return true;
-}
-
-static std::string getStretching(const KeyAuthentication& auth) {
- if (!auth.usesKeymaster()) {
- return kStretch_none;
- } else if (auth.secret.empty()) {
- return kStretch_nopassword;
- } else {
- char paramstr[PROPERTY_VALUE_MAX];
-
- property_get(SCRYPT_PROP, paramstr, SCRYPT_DEFAULTS);
- return std::string() + kStretchPrefix_scrypt + paramstr;
- }
-}
-
-static bool stretchingNeedsSalt(const std::string& stretching) {
- return stretching != kStretch_nopassword && stretching != kStretch_none;
-}
-
-static bool stretchSecret(const std::string& stretching, const std::string& secret,
- const std::string& salt, std::string* stretched) {
- if (stretching == kStretch_nopassword) {
- if (!secret.empty()) {
- LOG(WARNING) << "Password present but stretching is nopassword";
- // Continue anyway
- }
- stretched->clear();
- } else if (stretching == kStretch_none) {
- *stretched = secret;
- } else if (std::equal(kStretchPrefix_scrypt.begin(), kStretchPrefix_scrypt.end(),
- stretching.begin())) {
- int Nf, rf, pf;
- if (!parse_scrypt_parameters(stretching.substr(kStretchPrefix_scrypt.size()).c_str(), &Nf,
- &rf, &pf)) {
- LOG(ERROR) << "Unable to parse scrypt params in stretching: " << stretching;
- return false;
- }
- stretched->assign(STRETCHED_BYTES, '\0');
- if (crypto_scrypt(reinterpret_cast<const uint8_t*>(secret.data()), secret.size(),
- reinterpret_cast<const uint8_t*>(salt.data()), salt.size(), 1 << Nf,
- 1 << rf, 1 << pf, reinterpret_cast<uint8_t*>(&(*stretched)[0]),
- stretched->size()) != 0) {
- LOG(ERROR) << "scrypt failed with params: " << stretching;
- return false;
- }
- } else {
- LOG(ERROR) << "Unknown stretching type: " << stretching;
- return false;
- }
- return true;
-}
-
-static bool generateAppId(const KeyAuthentication& auth, const std::string& stretching,
- const std::string& salt, const std::string& secdiscardable_hash,
- std::string* appId) {
- std::string stretched;
- if (!stretchSecret(stretching, auth.secret, salt, &stretched)) return false;
- *appId = secdiscardable_hash + stretched;
- return true;
-}
-
-static void logOpensslError() {
- LOG(ERROR) << "Openssl error: " << ERR_get_error();
-}
-
-static bool encryptWithoutKeymaster(const std::string& preKey, const KeyBuffer& plaintext,
- std::string* ciphertext) {
- std::string key;
- hashWithPrefix(kHashPrefix_keygen, preKey, &key);
- key.resize(AES_KEY_BYTES);
- if (!readRandomBytesOrLog(GCM_NONCE_BYTES, ciphertext)) return false;
- auto ctx = std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>(
- EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
- if (!ctx) {
- logOpensslError();
- return false;
- }
- if (1 != EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_gcm(), NULL,
- reinterpret_cast<const uint8_t*>(key.data()),
- reinterpret_cast<const uint8_t*>(ciphertext->data()))) {
- logOpensslError();
- return false;
- }
- ciphertext->resize(GCM_NONCE_BYTES + plaintext.size() + GCM_MAC_BYTES);
- int outlen;
- if (1 != EVP_EncryptUpdate(
- ctx.get(), reinterpret_cast<uint8_t*>(&(*ciphertext)[0] + GCM_NONCE_BYTES),
- &outlen, reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size())) {
- logOpensslError();
- return false;
- }
- if (outlen != static_cast<int>(plaintext.size())) {
- LOG(ERROR) << "GCM ciphertext length should be " << plaintext.size() << " was " << outlen;
- return false;
- }
- if (1 != EVP_EncryptFinal_ex(
- ctx.get(),
- reinterpret_cast<uint8_t*>(&(*ciphertext)[0] + GCM_NONCE_BYTES + plaintext.size()),
- &outlen)) {
- logOpensslError();
- return false;
- }
- if (outlen != 0) {
- LOG(ERROR) << "GCM EncryptFinal should be 0, was " << outlen;
- return false;
- }
- if (1 != EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, GCM_MAC_BYTES,
- reinterpret_cast<uint8_t*>(&(*ciphertext)[0] + GCM_NONCE_BYTES +
- plaintext.size()))) {
- logOpensslError();
- return false;
- }
- return true;
-}
-
-static bool decryptWithoutKeymaster(const std::string& preKey, const std::string& ciphertext,
- KeyBuffer* plaintext) {
- if (ciphertext.size() < GCM_NONCE_BYTES + GCM_MAC_BYTES) {
- LOG(ERROR) << "GCM ciphertext too small: " << ciphertext.size();
- return false;
- }
- std::string key;
- hashWithPrefix(kHashPrefix_keygen, preKey, &key);
- key.resize(AES_KEY_BYTES);
- auto ctx = std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)>(
- EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
- if (!ctx) {
- logOpensslError();
- return false;
- }
- if (1 != EVP_DecryptInit_ex(ctx.get(), EVP_aes_256_gcm(), NULL,
- reinterpret_cast<const uint8_t*>(key.data()),
- reinterpret_cast<const uint8_t*>(ciphertext.data()))) {
- logOpensslError();
- return false;
- }
- *plaintext = KeyBuffer(ciphertext.size() - GCM_NONCE_BYTES - GCM_MAC_BYTES);
- int outlen;
- if (1 != EVP_DecryptUpdate(ctx.get(), reinterpret_cast<uint8_t*>(&(*plaintext)[0]), &outlen,
- reinterpret_cast<const uint8_t*>(ciphertext.data() + GCM_NONCE_BYTES),
- plaintext->size())) {
- logOpensslError();
- return false;
- }
- if (outlen != static_cast<int>(plaintext->size())) {
- LOG(ERROR) << "GCM plaintext length should be " << plaintext->size() << " was " << outlen;
- return false;
- }
- if (1 != EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, GCM_MAC_BYTES,
- const_cast<void*>(reinterpret_cast<const void*>(
- ciphertext.data() + GCM_NONCE_BYTES + plaintext->size())))) {
- logOpensslError();
- return false;
- }
- if (1 != EVP_DecryptFinal_ex(ctx.get(),
- reinterpret_cast<uint8_t*>(&(*plaintext)[0] + plaintext->size()),
- &outlen)) {
- logOpensslError();
- return false;
- }
- if (outlen != 0) {
- LOG(ERROR) << "GCM EncryptFinal should be 0, was " << outlen;
- return false;
- }
- return true;
-}
-
-bool pathExists(const std::string& path) {
- return access(path.c_str(), F_OK) == 0;
-}
-
-bool storeKey(const std::string& dir, const KeyAuthentication& auth, const KeyBuffer& key) {
- if (TEMP_FAILURE_RETRY(mkdir(dir.c_str(), 0700)) == -1) {
- PLOG(ERROR) << "key mkdir " << dir;
- return false;
- }
- if (!writeStringToFile(kCurrentVersion, dir + "/" + kFn_version)) return false;
- std::string secdiscardable_hash;
- if (!createSecdiscardable(dir + "/" + kFn_secdiscardable, &secdiscardable_hash)) return false;
- std::string stretching = getStretching(auth);
- if (!writeStringToFile(stretching, dir + "/" + kFn_stretching)) return false;
- std::string salt;
- if (stretchingNeedsSalt(stretching)) {
- if (ReadRandomBytes(SALT_BYTES, salt) != android::OK) {
- LOG(ERROR) << "Random read failed";
- return false;
- }
- if (!writeStringToFile(salt, dir + "/" + kFn_salt)) return false;
- }
- std::string appId;
- if (!generateAppId(auth, stretching, salt, secdiscardable_hash, &appId)) return false;
- std::string encryptedKey;
- if (auth.usesKeymaster()) {
- Keymaster keymaster;
- if (!keymaster) return false;
- std::string kmKey;
- if (!generateKeymasterKey(keymaster, auth, appId, &kmKey)) return false;
- if (!writeStringToFile(kmKey, dir + "/" + kFn_keymaster_key_blob)) return false;
- km::AuthorizationSet keyParams;
- km::HardwareAuthToken authToken;
- std::tie(keyParams, authToken) = beginParams(auth, appId);
- if (!encryptWithKeymasterKey(keymaster, dir, keyParams, authToken, key, &encryptedKey,
- false))
- return false;
- } else {
- if (!encryptWithoutKeymaster(appId, key, &encryptedKey)) return false;
- }
- if (!writeStringToFile(encryptedKey, dir + "/" + kFn_encrypted_key)) return false;
- if (!FsyncDirectory(dir)) return false;
- return true;
-}
-
-bool storeKeyAtomically(const std::string& key_path, const std::string& tmp_path,
- const KeyAuthentication& auth, const KeyBuffer& key) {
- if (pathExists(key_path)) {
- LOG(ERROR) << "Already exists, cannot create key at: " << key_path;
- return false;
- }
- if (pathExists(tmp_path)) {
- LOG(DEBUG) << "Already exists, destroying: " << tmp_path;
- destroyKey(tmp_path); // May be partially created so ignore errors
- }
- if (!::storeKey(tmp_path, auth, key)) return false;
- if (rename(tmp_path.c_str(), key_path.c_str()) != 0) {
- PLOG(ERROR) << "Unable to move new key to location: " << key_path;
- return false;
- }
- LOG(DEBUG) << "Created key: " << key_path;
- return true;
-}
-
-bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffer* key,
- bool keepOld) {
- std::string version;
- if (!readFileToString(dir + "/" + kFn_version, &version)) return false;
- if (version != kCurrentVersion) {
- LOG(ERROR) << "Version mismatch, expected " << kCurrentVersion << " got " << version;
- return false;
- }
- std::string secdiscardable_hash;
- if (!readSecdiscardable(dir + "/" + kFn_secdiscardable, &secdiscardable_hash)) return false;
- std::string stretching;
- if (!readFileToString(dir + "/" + kFn_stretching, &stretching)) return false;
- std::string salt;
- if (stretchingNeedsSalt(stretching)) {
- if (!readFileToString(dir + "/" + kFn_salt, &salt)) return false;
- }
- std::string appId;
- if (!generateAppId(auth, stretching, salt, secdiscardable_hash, &appId)) return false;
- std::string encryptedMessage;
- if (!readFileToString(dir + "/" + kFn_encrypted_key, &encryptedMessage)) return false;
- if (auth.usesKeymaster()) {
- Keymaster keymaster;
- if (!keymaster) return false;
- km::AuthorizationSet keyParams;
- km::HardwareAuthToken authToken;
- std::tie(keyParams, authToken) = beginParams(auth, appId);
- if (!decryptWithKeymasterKey(keymaster, dir, keyParams, authToken, encryptedMessage, key,
- keepOld))
- return false;
- } else {
- if (!decryptWithoutKeymaster(appId, encryptedMessage, key)) return false;
- }
- return true;
-}
-
-static bool deleteKey(const std::string& dir) {
- std::string kmKey;
- if (!readFileToString(dir + "/" + kFn_keymaster_key_blob, &kmKey)) return false;
- // In A12 keymaster_key_blob format changed:
- // it have useless for us bytes in beginning, so remove them to correctly handle key
- if (!kmKey.compare(0, kPkmBlob.size(), kPkmBlob))
- kmKey.erase(0, kPkmBlob.size());
- Keymaster keymaster;
- if (!keymaster) return false;
- if (!keymaster.deleteKey(kmKey)) return false;
- return true;
-}
-
-bool runSecdiscardSingle(const std::string& file) {
- if (ForkExecvp(std::vector<std::string>{kSecdiscardPath, "--", file}) != 0) {
- LOG(ERROR) << "secdiscard failed";
- return false;
- }
- return true;
-}
-
-static bool recursiveDeleteKey(const std::string& dir) {
- if (ForkExecvp(std::vector<std::string>{kRmPath, "-rf", dir}) != 0) {
- LOG(ERROR) << "recursive delete failed";
- return false;
- }
- return true;
-}
-
-bool destroyKey(const std::string& dir) {
- bool success = true;
- // Try each thing, even if previous things failed.
- bool uses_km = pathExists(dir + "/" + kFn_keymaster_key_blob);
- if (uses_km) {
- success &= deleteKey(dir);
- }
- auto secdiscard_cmd = std::vector<std::string>{
- kSecdiscardPath,
- "--",
- dir + "/" + kFn_encrypted_key,
- dir + "/" + kFn_secdiscardable,
- };
- if (uses_km) {
- secdiscard_cmd.emplace_back(dir + "/" + kFn_keymaster_key_blob);
- }
- if (ForkExecvp(secdiscard_cmd) != 0) {
- LOG(ERROR) << "secdiscard failed";
- success = false;
- }
- success &= recursiveDeleteKey(dir);
- return success;
-}
diff --git a/crypto/fscrypt/KeyStorage.h b/crypto/fscrypt/KeyStorage.h
deleted file mode 100755
index 2c88820..0000000
--- a/crypto/fscrypt/KeyStorage.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_VOLD_KEYSTORAGE_H
-#define ANDROID_VOLD_KEYSTORAGE_H
-
-#include "KeyBuffer.h"
-
-#include <string>
-
-
-// Represents the information needed to decrypt a disk encryption key.
-// If "token" is nonempty, it is passed in as a required Gatekeeper auth token.
-// If "token" and "secret" are nonempty, "secret" is appended to the application-specific
-// binary needed to unlock.
-// If only "secret" is nonempty, it is used to decrypt in a non-Keymaster process.
-class KeyAuthentication {
- public:
- KeyAuthentication(const std::string& t, const std::string& s) : token{t}, secret{s} {};
-
- bool usesKeymaster() const { return !token.empty() || secret.empty(); };
-
- const std::string token;
- const std::string secret;
-};
-
-extern const KeyAuthentication kEmptyAuthentication;
-
-// Checks if path "path" exists.
-bool pathExists(const std::string& path);
-
-bool createSecdiscardable(const std::string& path, std::string* hash);
-bool readSecdiscardable(const std::string& path, std::string* hash);
-
-// Create a directory at the named path, and store "key" in it,
-// in such a way that it can only be retrieved via Keymaster and
-// can be securely deleted.
-// It's safe to move/rename the directory after creation.
-bool storeKey(const std::string& dir, const KeyAuthentication& auth, const KeyBuffer& key);
-
-// Create a directory at the named path, and store "key" in it as storeKey
-// This version creates the key in "tmp_path" then atomically renames "tmp_path"
-// to "key_path" thereby ensuring that the key is either stored entirely or
-// not at all.
-bool storeKeyAtomically(const std::string& key_path, const std::string& tmp_path,
- const KeyAuthentication& auth, const KeyBuffer& key);
-
-// Retrieve the key from the named directory.
-bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffer* key,
- bool keepOld);
-
-// Securely destroy the key stored in the named directory and delete the directory.
-bool destroyKey(const std::string& dir);
-
-bool runSecdiscardSingle(const std::string& file);
-
-// Generate wrapped storage key using keymaster. Uses STORAGE_KEY tag in keymaster.
-bool generateWrappedStorageKey(KeyBuffer* key);
-// Export the per-boot boot wrapped storage key using keymaster.
-bool exportWrappedStorageKey(const KeyBuffer& kmKey, KeyBuffer* key);
-
-#endif
diff --git a/crypto/fscrypt/KeyUtil.cpp b/crypto/fscrypt/KeyUtil.cpp
deleted file mode 100755
index b7119a6..0000000
--- a/crypto/fscrypt/KeyUtil.cpp
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright (C) 2016 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 "KeyUtil.h"
-
-#include <iomanip>
-#include <sstream>
-#include <string>
-
-#include <fcntl.h>
-#include <linux/fscrypt.h>
-#include <openssl/sha.h>
-#include <sys/ioctl.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <keyutils.h>
-
-#include <fscrypt_uapi.h>
-#include "FsCrypt.h"
-#include "KeyStorage.h"
-#include "Utils.h"
-
-
-const KeyGeneration neverGen() {
- return KeyGeneration{0, false, false};
-}
-
-static bool randomKey(size_t size, KeyBuffer* key) {
- *key = KeyBuffer(size);
- if (ReadRandomBytes(key->size(), key->data()) != 0) {
- // TODO status_t plays badly with PLOG, fix it.
- LOG(ERROR) << "Random read failed";
- return false;
- }
- return true;
-}
-
-bool generateStorageKey(const KeyGeneration& gen, KeyBuffer* key) {
- if (!gen.allow_gen) return false;
- if (gen.use_hw_wrapped_key) {
- if (gen.keysize != FSCRYPT_MAX_KEY_SIZE) {
- LOG(ERROR) << "Cannot generate a wrapped key " << gen.keysize << " bytes long";
- return false;
- }
- return generateWrappedStorageKey(key);
- } else {
- return randomKey(gen.keysize, key);
- }
-}
-
-// Return true if the kernel supports the ioctls to add/remove fscrypt keys
-// directly to/from the filesystem.
-bool isFsKeyringSupported(void) {
- static bool initialized = false;
- static bool supported;
-
- if (!initialized) {
- android::base::unique_fd fd(open("/data", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
-
- // FS_IOC_ADD_ENCRYPTION_KEY with a NULL argument will fail with ENOTTY
- // if the ioctl isn't supported. Otherwise it will fail with another
- // error code such as EFAULT.
- errno = 0;
- (void)ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, NULL);
- if (errno == ENOTTY) {
- LOG(INFO) << "Kernel doesn't support FS_IOC_ADD_ENCRYPTION_KEY. Falling back to "
- "session keyring";
- supported = false;
- } else {
- if (errno != EFAULT) {
- PLOG(WARNING) << "Unexpected error from FS_IOC_ADD_ENCRYPTION_KEY";
- }
- LOG(INFO) << "Detected support for FS_IOC_ADD_ENCRYPTION_KEY";
- supported = true;
- android::base::SetProperty("ro.crypto.uses_fs_ioc_add_encryption_key", "true");
- }
- // There's no need to check for FS_IOC_REMOVE_ENCRYPTION_KEY, since it's
- // guaranteed to be available if FS_IOC_ADD_ENCRYPTION_KEY is. There's
- // also no need to check for support on external volumes separately from
- // /data, since either the kernel supports the ioctls on all
- // fscrypt-capable filesystems or it doesn't.
-
- initialized = true;
- }
- return supported;
-}
-
-// Get raw keyref - used to make keyname and to pass to ioctl
-static std::string generateKeyRef(const uint8_t* key, int length) {
- SHA512_CTX c;
-
- SHA512_Init(&c);
- SHA512_Update(&c, key, length);
- unsigned char key_ref1[SHA512_DIGEST_LENGTH];
- SHA512_Final(key_ref1, &c);
-
- SHA512_Init(&c);
- SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
- unsigned char key_ref2[SHA512_DIGEST_LENGTH];
- SHA512_Final(key_ref2, &c);
-
- static_assert(FSCRYPT_KEY_DESCRIPTOR_SIZE <= SHA512_DIGEST_LENGTH,
- "Hash too short for descriptor");
- return std::string((char*)key_ref2, FSCRYPT_KEY_DESCRIPTOR_SIZE);
-}
-
-static bool fillKey(const KeyBuffer& key, fscrypt_key* fs_key) {
- if (key.size() != FSCRYPT_MAX_KEY_SIZE) {
- LOG(ERROR) << "Wrong size key " << key.size();
- return false;
- }
- static_assert(FSCRYPT_MAX_KEY_SIZE == sizeof(fs_key->raw), "Mismatch of max key sizes");
- fs_key->mode = 0; // unused by kernel
- memcpy(fs_key->raw, key.data(), key.size());
- fs_key->size = key.size();
- return true;
-}
-
-static char const* const NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt", nullptr};
-
-static std::string keyrefstring(const std::string& raw_ref) {
- std::ostringstream o;
- for (unsigned char i : raw_ref) {
- o << std::hex << std::setw(2) << std::setfill('0') << (int)i;
- }
- return o.str();
-}
-
-static std::string buildLegacyKeyName(const std::string& prefix, const std::string& raw_ref) {
- return prefix + ":" + keyrefstring(raw_ref);
-}
-
-// Get the ID of the keyring we store all fscrypt keys in when the kernel is too
-// old to support FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY.
-static bool fscryptKeyring(key_serial_t* device_keyring) {
- *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
- if (*device_keyring == -1) {
- PLOG(ERROR) << "Unable to find device keyring";
- return false;
- }
- return true;
-}
-
-// Add an encryption key of type "logon" to the global session keyring.
-static bool installKeyLegacy(const KeyBuffer& key, const std::string& raw_ref) {
- // Place fscrypt_key into automatically zeroing buffer.
- KeyBuffer fsKeyBuffer(sizeof(fscrypt_key));
- fscrypt_key& fs_key = *reinterpret_cast<fscrypt_key*>(fsKeyBuffer.data());
-
- if (!fillKey(key, &fs_key)) return false;
- key_serial_t device_keyring;
- if (!fscryptKeyring(&device_keyring)) return false;
- for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
- auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
- key_serial_t key_id =
- add_key("logon", ref.c_str(), (void*)&fs_key, sizeof(fs_key), device_keyring);
- if (key_id == -1) {
- PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
- return false;
- }
- LOG(INFO) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
- << " in process " << getpid();
- }
- return true;
-}
-
-// Installs fscrypt-provisioning key into session level kernel keyring.
-// This allows for the given key to be installed back into filesystem keyring.
-// For more context see reloadKeyFromSessionKeyring.
-static bool installProvisioningKey(const KeyBuffer& key, const std::string& ref,
- const fscrypt_key_specifier& key_spec) {
- key_serial_t device_keyring;
- if (!fscryptKeyring(&device_keyring)) return false;
-
- // Place fscrypt_provisioning_key_payload into automatically zeroing buffer.
- KeyBuffer buf(sizeof(fscrypt_provisioning_key_payload) + key.size(), 0);
- fscrypt_provisioning_key_payload& provisioning_key =
- *reinterpret_cast<fscrypt_provisioning_key_payload*>(buf.data());
- memcpy(provisioning_key.raw, key.data(), key.size());
- provisioning_key.type = key_spec.type;
-
- key_serial_t key_id = add_key("fscrypt-provisioning", ref.c_str(), (void*)&provisioning_key,
- buf.size(), device_keyring);
- if (key_id == -1) {
- PLOG(ERROR) << "Failed to insert fscrypt-provisioning key for " << ref
- << " into session keyring";
- return false;
- }
- LOG(INFO) << "Added fscrypt-provisioning key for " << ref << " to session keyring";
- return true;
-}
-
-// Build a struct fscrypt_key_specifier for use in the key management ioctls.
-static bool buildKeySpecifier(fscrypt_key_specifier* spec, const EncryptionPolicy& policy) {
- switch (policy.options.version) {
- case 1:
- if (policy.key_raw_ref.size() != FSCRYPT_KEY_DESCRIPTOR_SIZE) {
- LOG(ERROR) << "Invalid key specifier size for v1 encryption policy: "
- << policy.key_raw_ref.size();
- return false;
- }
- spec->type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
- memcpy(spec->u.descriptor, policy.key_raw_ref.c_str(), FSCRYPT_KEY_DESCRIPTOR_SIZE);
- return true;
- case 2:
- if (policy.key_raw_ref.size() != FSCRYPT_KEY_IDENTIFIER_SIZE) {
- LOG(ERROR) << "Invalid key specifier size for v2 encryption policy: "
- << policy.key_raw_ref.size();
- return false;
- }
- spec->type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
- memcpy(spec->u.identifier, policy.key_raw_ref.c_str(), FSCRYPT_KEY_IDENTIFIER_SIZE);
- return true;
- default:
- LOG(ERROR) << "Invalid encryption policy version: " << policy.options.version;
- return false;
- }
-}
-
-// Installs key into keyring of a filesystem mounted on |mountpoint|.
-//
-// It's callers responsibility to fill key specifier, and either arg->raw or arg->key_id.
-//
-// In case arg->key_spec.type equals to FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER
-// arg->key_spec.u.identifier will be populated with raw key reference generated
-// by kernel.
-//
-// For documentation on difference between arg->raw and arg->key_id see
-// https://www.kernel.org/doc/html/latest/filesystems/fscrypt.html#fs-ioc-add-encryption-key
-static bool installFsKeyringKey(const std::string& mountpoint, const EncryptionOptions& options,
- fscrypt_add_key_arg* arg) {
- if (options.use_hw_wrapped_key) arg->flags |= FSCRYPT_ADD_KEY_FLAG_WRAPPED;
-
- android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open " << mountpoint << " to install key";
- return false;
- }
-
- if (ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, arg) != 0) {
- PLOG(ERROR) << "Failed to install fscrypt key to " << mountpoint;
- return false;
- }
-
- return true;
-}
-
-bool installKey(const std::string& mountpoint, const EncryptionOptions& options,
- const KeyBuffer& key, EncryptionPolicy* policy) {
- policy->options = options;
- // Put the fscrypt_add_key_arg in an automatically-zeroing buffer, since we
- // have to copy the raw key into it.
- KeyBuffer arg_buf(sizeof(struct fscrypt_add_key_arg) + key.size(), 0);
- struct fscrypt_add_key_arg* arg = (struct fscrypt_add_key_arg*)arg_buf.data();
-
- // Initialize the "key specifier", which is like a name for the key.
- switch (options.version) {
- case 1:
- // A key for a v1 policy is specified by an arbitrary 8-byte
- // "descriptor", which must be provided by userspace. We use the
- // first 8 bytes from the double SHA-512 of the key itself.
- if (options.use_hw_wrapped_key) {
- // When wrapped key is supported, only the first 32 bytes are
- // the same per boot. The second 32 bytes can change as the ephemeral
- // key is different.
- policy->key_raw_ref = generateKeyRef((const uint8_t*)key.data(), key.size()/2);
- } else {
- policy->key_raw_ref = generateKeyRef((const uint8_t*)key.data(), key.size());
- }
- if (!isFsKeyringSupported()) {
- return installKeyLegacy(key, policy->key_raw_ref);
- }
- if (!buildKeySpecifier(&arg->key_spec, *policy)) {
- return false;
- }
- break;
- case 2:
- // A key for a v2 policy is specified by an 16-byte "identifier",
- // which is a cryptographic hash of the key itself which the kernel
- // computes and returns. Any user-provided value is ignored; we
- // just need to set the specifier type to indicate that we're adding
- // this type of key.
- arg->key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
- break;
- default:
- LOG(ERROR) << "Invalid encryption policy version: " << options.version;
- return false;
- }
-
- arg->raw_size = key.size();
- memcpy(arg->raw, key.data(), key.size());
-
- if (!installFsKeyringKey(mountpoint, options, arg)) return false;
-
- if (arg->key_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
- // Retrieve the key identifier that the kernel computed.
- policy->key_raw_ref =
- std::string((char*)arg->key_spec.u.identifier, FSCRYPT_KEY_IDENTIFIER_SIZE);
- }
- std::string ref = keyrefstring(policy->key_raw_ref);
- LOG(INFO) << "Installed fscrypt key with ref " << ref << " to " << mountpoint;
-
- if (!installProvisioningKey(key, ref, arg->key_spec)) return false;
- return true;
-}
-
-// Remove an encryption key of type "logon" from the global session keyring.
-static bool evictKeyLegacy(const std::string& raw_ref) {
- key_serial_t device_keyring;
- if (!fscryptKeyring(&device_keyring)) return false;
- bool success = true;
- for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
- auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
- auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
-
- // Unlink the key from the keyring. Prefer unlinking to revoking or
- // invalidating, since unlinking is actually no less secure currently, and
- // it avoids bugs in certain kernel versions where the keyring key is
- // referenced from places it shouldn't be.
- if (keyctl_unlink(key_serial, device_keyring) != 0) {
- PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
- success = false;
- } else {
- LOG(ERROR) << "Unlinked key with serial " << key_serial << " ref " << ref;
- }
- }
- return success;
-}
-
-static bool evictProvisioningKey(const std::string& ref) {
- key_serial_t device_keyring;
- if (!fscryptKeyring(&device_keyring)) {
- return false;
- }
-
- auto key_serial = keyctl_search(device_keyring, "fscrypt-provisioning", ref.c_str(), 0);
- if (key_serial == -1 && errno != ENOKEY) {
- PLOG(ERROR) << "Error searching session keyring for fscrypt-provisioning key for " << ref;
- return false;
- }
-
- if (key_serial != -1 && keyctl_unlink(key_serial, device_keyring) != 0) {
- PLOG(ERROR) << "Failed to unlink fscrypt-provisioning key for " << ref
- << " from session keyring";
- return false;
- }
- return true;
-}
-
-bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy) {
- if (policy.options.version == 1 && !isFsKeyringSupported()) {
- return evictKeyLegacy(policy.key_raw_ref);
- }
-
- android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open " << mountpoint << " to evict key";
- return false;
- }
-
- struct fscrypt_remove_key_arg arg;
- memset(&arg, 0, sizeof(arg));
-
- if (!buildKeySpecifier(&arg.key_spec, policy)) {
- return false;
- }
-
- std::string ref = keyrefstring(policy.key_raw_ref);
-
- if (ioctl(fd, FS_IOC_REMOVE_ENCRYPTION_KEY, &arg) != 0) {
- PLOG(ERROR) << "Failed to evict fscrypt key with ref " << ref << " from " << mountpoint;
- return false;
- }
-
- LOG(ERROR) << "Evicted fscrypt key with ref " << ref << " from " << mountpoint;
- if (arg.removal_status_flags & FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS) {
- // Should never happen because keys are only added/removed as root.
- LOG(ERROR) << "Unexpected case: key with ref " << ref << " is still added by other users!";
- } else if (arg.removal_status_flags & FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY) {
- LOG(ERROR) << "Files still open after removing key with ref " << ref
- << ". These files were not locked!";
- }
-
- if (!evictProvisioningKey(ref)) return false;
- return true;
-}
-
-bool retrieveOrGenerateKey(const std::string& key_path, const std::string& tmp_path,
- const KeyAuthentication& key_authentication, const KeyGeneration& gen,
- KeyBuffer* key, bool keepOld) {
- if (pathExists(key_path)) {
- LOG(INFO) << "Key exists, using: " << key_path;
- if (!retrieveKey(key_path, key_authentication, key, keepOld)) return false;
- } else {
- if (!gen.allow_gen) {
- LOG(ERROR) << "No key found in " << key_path;
- return false;
- }
- LOG(INFO) << "Creating new key in " << key_path;
- if (!::generateStorageKey(gen, key)) return false;
- if (!storeKeyAtomically(key_path, tmp_path, key_authentication, *key)) return false;
- }
- return true;
-}
-
-bool reloadKeyFromSessionKeyring(const std::string& mountpoint, const EncryptionPolicy& policy) {
- key_serial_t device_keyring;
- if (!fscryptKeyring(&device_keyring)) {
- return false;
- }
-
- std::string ref = keyrefstring(policy.key_raw_ref);
- auto key_serial = keyctl_search(device_keyring, "fscrypt-provisioning", ref.c_str(), 0);
- if (key_serial == -1) {
- PLOG(ERROR) << "Failed to find fscrypt-provisioning key for " << ref
- << " in session keyring";
- return false;
- }
-
- LOG(INFO) << "Installing fscrypt-provisioning key for " << ref << " back into " << mountpoint
- << " fs-keyring";
-
- struct fscrypt_add_key_arg arg;
- memset(&arg, 0, sizeof(arg));
- if (!buildKeySpecifier(&arg.key_spec, policy)) return false;
- arg.key_id = key_serial;
- if (!installFsKeyringKey(mountpoint, policy.options, &arg)) return false;
-
- return true;
-}
diff --git a/crypto/fscrypt/KeyUtil.h b/crypto/fscrypt/KeyUtil.h
deleted file mode 100755
index dcfcde8..0000000
--- a/crypto/fscrypt/KeyUtil.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_VOLD_KEYUTIL_H
-#define ANDROID_VOLD_KEYUTIL_H
-
-#include "KeyBuffer.h"
-#include "KeyStorage.h"
-
-#include <fscrypt/fscrypt.h>
-
-#include <memory>
-#include <string>
-
-
-using namespace android::fscrypt;
-
-// Description of how to generate a key when needed.
-struct KeyGeneration {
- size_t keysize;
- bool allow_gen;
- bool use_hw_wrapped_key;
-};
-
-// Generate a key as specified in KeyGeneration
-bool generateStorageKey(const KeyGeneration& gen, KeyBuffer* key);
-
-// Returns a key with allow_gen false so generateStorageKey returns false;
-// this is used to indicate to retrieveOrGenerateKey that a key should not
-// be generated.
-const KeyGeneration neverGen();
-
-bool isFsKeyringSupported(void);
-
-// Install a file-based encryption key to the kernel, for use by encrypted files
-// on the specified filesystem using the specified encryption policy version.
-//
-// For v1 policies, we use FS_IOC_ADD_ENCRYPTION_KEY if the kernel supports it.
-// Otherwise we add the key to the global session keyring as a "logon" key.
-//
-// For v2 policies, we always use FS_IOC_ADD_ENCRYPTION_KEY; it's the only way
-// the kernel supports.
-//
-// If kernel supports FS_IOC_ADD_ENCRYPTION_KEY, also installs key of
-// fscrypt-provisioning type to the global session keyring. This makes it
-// possible to unmount and then remount mountpoint without losing the file-based
-// key.
-//
-// Returns %true on success, %false on failure. On success also sets *policy
-// to the EncryptionPolicy used to refer to this key.
-bool installKey(const std::string& mountpoint, const EncryptionOptions& options,
- const KeyBuffer& key, EncryptionPolicy* policy);
-
-// Evict a file-based encryption key from the kernel.
-//
-// This undoes the effect of installKey().
-//
-// If the kernel doesn't support the filesystem-level keyring, the caller is
-// responsible for dropping caches.
-bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy);
-
-bool retrieveOrGenerateKey(const std::string& key_path, const std::string& tmp_path,
- const KeyAuthentication& key_authentication, const KeyGeneration& gen,
- KeyBuffer* key, bool keepOld = true);
-
-// Re-installs a file-based encryption key of fscrypt-provisioning type from the
-// global session keyring back into fs keyring of the mountpoint.
-bool reloadKeyFromSessionKeyring(const std::string& mountpoint, const EncryptionPolicy& policy);
-
-#endif
diff --git a/crypto/fscrypt/Keymaster.cpp b/crypto/fscrypt/Keymaster.cpp
deleted file mode 100755
index c5b7bc3..0000000
--- a/crypto/fscrypt/Keymaster.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2016 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 "Keymaster.h"
-
-#include <android-base/logging.h>
-#include <keymasterV4_1/authorization_set.h>
-#include <keymasterV4_1/keymaster_utils.h>
-
-
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::keymaster::V4_0::SecurityLevel;
-
-KeymasterOperation::~KeymasterOperation() {
- if (mDevice) mDevice->abort(mOpHandle);
-}
-
-bool KeymasterOperation::updateCompletely(const char* input, size_t inputLen,
- const std::function<void(const char*, size_t)> consumer) {
- uint32_t inputConsumed = 0;
-
- km::ErrorCode km_error;
- auto hidlCB = [&](km::ErrorCode ret, uint32_t inputConsumedDelta,
- const hidl_vec<km::KeyParameter>& /*ignored*/,
- const hidl_vec<uint8_t>& _output) {
- km_error = ret;
- if (km_error != km::ErrorCode::OK) return;
- inputConsumed += inputConsumedDelta;
- consumer(reinterpret_cast<const char*>(&_output[0]), _output.size());
- };
-
- while (inputConsumed != inputLen) {
- size_t toRead = static_cast<size_t>(inputLen - inputConsumed);
- auto inputBlob = km::support::blob2hidlVec(
- reinterpret_cast<const uint8_t*>(&input[inputConsumed]), toRead);
- auto error = mDevice->update(mOpHandle, hidl_vec<km::KeyParameter>(), inputBlob,
- km::HardwareAuthToken(), km::VerificationToken(), hidlCB);
- if (!error.isOk()) {
- LOG(ERROR) << "update failed: " << error.description();
- mDevice = nullptr;
- return false;
- }
- if (km_error != km::ErrorCode::OK) {
- LOG(ERROR) << "update failed, code " << int32_t(km_error);
- mDevice = nullptr;
- return false;
- }
- if (inputConsumed > inputLen) {
- LOG(ERROR) << "update reported too much input consumed";
- mDevice = nullptr;
- return false;
- }
- }
- return true;
-}
-
-bool KeymasterOperation::finish(std::string* output) {
- km::ErrorCode km_error;
- auto hidlCb = [&](km::ErrorCode ret, const hidl_vec<km::KeyParameter>& /*ignored*/,
- const hidl_vec<uint8_t>& _output) {
- km_error = ret;
- if (km_error != km::ErrorCode::OK) return;
- if (output) output->assign(reinterpret_cast<const char*>(&_output[0]), _output.size());
- };
- auto error = mDevice->finish(mOpHandle, hidl_vec<km::KeyParameter>(), hidl_vec<uint8_t>(),
- hidl_vec<uint8_t>(), km::HardwareAuthToken(),
- km::VerificationToken(), hidlCb);
- mDevice = nullptr;
- if (!error.isOk()) {
- LOG(ERROR) << "finish failed: " << error.description();
- return false;
- }
- if (km_error != km::ErrorCode::OK) {
- LOG(ERROR) << "finish failed, code " << int32_t(km_error);
- return false;
- }
- return true;
-}
-
-/* static */ bool Keymaster::hmacKeyGenerated = false;
-
-Keymaster::Keymaster() {
- auto devices = KmDevice::enumerateAvailableDevices();
- if (!hmacKeyGenerated) {
- KmDevice::performHmacKeyAgreement(devices);
- hmacKeyGenerated = true;
- }
- for (auto& dev : devices) {
- // Do not use StrongBox for device encryption / credential encryption. If a security chip
- // is present it will have Weaver, which already strengthens CE. We get no additional
- // benefit from using StrongBox here, so skip it.
- if (dev->halVersion().securityLevel != SecurityLevel::STRONGBOX) {
- mDevice = std::move(dev);
- break;
- }
- }
- if (!mDevice) return;
- auto& version = mDevice->halVersion();
- LOG(INFO) << "Using " << version.keymasterName << " from " << version.authorName
- << " for encryption. Security level: " << toString(version.securityLevel)
- << ", HAL: " << mDevice->descriptor() << "/" << mDevice->instanceName();
-}
-
-bool Keymaster::generateKey(const km::AuthorizationSet& inParams, std::string* key) {
- km::ErrorCode km_error;
- auto hidlCb = [&](km::ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
- const km::KeyCharacteristics& /*ignored*/) {
- km_error = ret;
- if (km_error != km::ErrorCode::OK) return;
- if (key) key->assign(reinterpret_cast<const char*>(&keyBlob[0]), keyBlob.size());
- };
-
- auto error = mDevice->generateKey(inParams.hidl_data(), hidlCb);
- if (!error.isOk()) {
- LOG(ERROR) << "generate_key failed: " << error.description();
- return false;
- }
- if (km_error != km::ErrorCode::OK) {
- LOG(ERROR) << "generate_key failed, code " << int32_t(km_error);
- return false;
- }
- return true;
-}
-
-km::ErrorCode Keymaster::exportKey(const KeyBuffer& kmKey, std::string* key) {
- auto kmKeyBlob = km::support::blob2hidlVec(std::string(kmKey.data(), kmKey.size()));
- km::ErrorCode km_error;
- auto hidlCb = [&](km::ErrorCode ret, const hidl_vec<uint8_t>& exportedKeyBlob) {
- km_error = ret;
- if (km_error != km::ErrorCode::OK) return;
- if (key)
- key->assign(reinterpret_cast<const char*>(&exportedKeyBlob[0]), exportedKeyBlob.size());
- };
- auto error = mDevice->exportKey(km::KeyFormat::RAW, kmKeyBlob, {}, {}, hidlCb);
- if (!error.isOk()) {
- LOG(ERROR) << "export_key failed: " << error.description();
- return km::ErrorCode::UNKNOWN_ERROR;
- }
- if (km_error != km::ErrorCode::OK) {
- LOG(ERROR) << "export_key failed, code " << int32_t(km_error);
- return km_error;
- }
- return km::ErrorCode::OK;
-}
-
-bool Keymaster::deleteKey(const std::string& key) {
- auto keyBlob = km::support::blob2hidlVec(key);
- auto error = mDevice->deleteKey(keyBlob);
- if (!error.isOk()) {
- LOG(ERROR) << "delete_key failed: " << error.description();
- return false;
- }
- if (error != km::ErrorCode::OK) {
- LOG(ERROR) << "delete_key failed, code " << int32_t(km::ErrorCode(error));
- return false;
- }
- return true;
-}
-
-bool Keymaster::upgradeKey(const std::string& oldKey, const km::AuthorizationSet& inParams,
- std::string* newKey) {
- auto oldKeyBlob = km::support::blob2hidlVec(oldKey);
- km::ErrorCode km_error;
- auto hidlCb = [&](km::ErrorCode ret, const hidl_vec<uint8_t>& upgradedKeyBlob) {
- km_error = ret;
- if (km_error != km::ErrorCode::OK) return;
- if (newKey)
- newKey->assign(reinterpret_cast<const char*>(&upgradedKeyBlob[0]),
- upgradedKeyBlob.size());
- };
- auto error = mDevice->upgradeKey(oldKeyBlob, inParams.hidl_data(), hidlCb);
- if (!error.isOk()) {
- LOG(ERROR) << "upgrade_key failed: " << error.description();
- return false;
- }
- if (km_error != km::ErrorCode::OK) {
- LOG(ERROR) << "upgrade_key failed, code " << int32_t(km_error);
- return false;
- }
- return true;
-}
-
-KeymasterOperation Keymaster::begin(km::KeyPurpose purpose, const std::string& key,
- const km::AuthorizationSet& inParams,
- const km::HardwareAuthToken& authToken,
- km::AuthorizationSet* outParams) {
- auto keyBlob = km::support::blob2hidlVec(key);
- uint64_t mOpHandle;
- km::ErrorCode km_error;
-
- auto hidlCb = [&](km::ErrorCode ret, const hidl_vec<km::KeyParameter>& _outParams,
- uint64_t operationHandle) {
- km_error = ret;
- if (km_error != km::ErrorCode::OK) return;
- if (outParams) *outParams = _outParams;
- mOpHandle = operationHandle;
- };
-
- auto error = mDevice->begin(purpose, keyBlob, inParams.hidl_data(), authToken, hidlCb);
- if (!error.isOk()) {
- LOG(ERROR) << "begin failed: " << error.description();
- return KeymasterOperation(km::ErrorCode::UNKNOWN_ERROR);
- }
- if (km_error != km::ErrorCode::OK) {
- LOG(ERROR) << "begin failed, code " << int32_t(km_error);
- return KeymasterOperation(km_error);
- }
- return KeymasterOperation(mDevice.get(), mOpHandle);
-}
-
-bool Keymaster::isSecure() {
- return mDevice->halVersion().securityLevel != km::SecurityLevel::SOFTWARE;
-}
-
-void Keymaster::earlyBootEnded() {
- auto devices = KmDevice::enumerateAvailableDevices();
- for (auto& dev : devices) {
- auto error = dev->earlyBootEnded();
- if (!error.isOk()) {
- LOG(ERROR) << "earlyBootEnded call failed: " << error.description() << " for "
- << dev->halVersion().keymasterName;
- }
- km::V4_1_ErrorCode km_error = error;
- if (km_error != km::V4_1_ErrorCode::OK && km_error != km::V4_1_ErrorCode::UNIMPLEMENTED) {
- LOG(ERROR) << "Error reporting early boot ending to keymaster: "
- << static_cast<int32_t>(km_error) << " for "
- << dev->halVersion().keymasterName;
- }
- }
-}
-
-int keymaster_compatibility_cryptfs_scrypt() {
- Keymaster dev;
- if (!dev) {
- LOG(ERROR) << "Failed to initiate keymaster session";
- return -1;
- }
- return dev.isSecure();
-}
-
-static bool write_string_to_buf(const std::string& towrite, uint8_t* buffer, uint32_t buffer_size,
- uint32_t* out_size) {
- if (!buffer || !out_size) {
- LOG(ERROR) << "Missing target pointers";
- return false;
- }
- *out_size = towrite.size();
- if (buffer_size < towrite.size()) {
- LOG(ERROR) << "Buffer too small " << buffer_size << " < " << towrite.size();
- return false;
- }
- memset(buffer, '\0', buffer_size);
- std::copy(towrite.begin(), towrite.end(), buffer);
- return true;
-}
-
-static km::AuthorizationSet keyParams(uint32_t rsa_key_size, uint64_t rsa_exponent,
- uint32_t ratelimit) {
- return km::AuthorizationSetBuilder()
- .RsaSigningKey(rsa_key_size, rsa_exponent)
- .NoDigestOrPadding()
- .Authorization(km::TAG_BLOB_USAGE_REQUIREMENTS, km::KeyBlobUsageRequirements::STANDALONE)
- .Authorization(km::TAG_NO_AUTH_REQUIRED)
- .Authorization(km::TAG_MIN_SECONDS_BETWEEN_OPS, ratelimit);
-}
-
-int keymaster_create_key_for_cryptfs_scrypt(uint32_t rsa_key_size, uint64_t rsa_exponent,
- uint32_t ratelimit, uint8_t* key_buffer,
- uint32_t key_buffer_size, uint32_t* key_out_size) {
- if (key_out_size) {
- *key_out_size = 0;
- }
- Keymaster dev;
- if (!dev) {
- LOG(ERROR) << "Failed to initiate keymaster session";
- return -1;
- }
- std::string key;
- if (!dev.generateKey(keyParams(rsa_key_size, rsa_exponent, ratelimit), &key)) return -1;
- if (!write_string_to_buf(key, key_buffer, key_buffer_size, key_out_size)) return -1;
- return 0;
-}
-
-int keymaster_upgrade_key_for_cryptfs_scrypt(uint32_t rsa_key_size, uint64_t rsa_exponent,
- uint32_t ratelimit, const uint8_t* key_blob,
- size_t key_blob_size, uint8_t* key_buffer,
- uint32_t key_buffer_size, uint32_t* key_out_size) {
- if (key_out_size) {
- *key_out_size = 0;
- }
- Keymaster dev;
- if (!dev) {
- LOG(ERROR) << "Failed to initiate keymaster session";
- return -1;
- }
- std::string old_key(reinterpret_cast<const char*>(key_blob), key_blob_size);
- std::string new_key;
- if (!dev.upgradeKey(old_key, keyParams(rsa_key_size, rsa_exponent, ratelimit), &new_key))
- return -1;
- if (!write_string_to_buf(new_key, key_buffer, key_buffer_size, key_out_size)) return -1;
- return 0;
-}
-
-KeymasterSignResult keymaster_sign_object_for_cryptfs_scrypt(
- const uint8_t* key_blob, size_t key_blob_size, uint32_t ratelimit, const uint8_t* object,
- const size_t object_size, uint8_t** signature_buffer, size_t* signature_buffer_size) {
- Keymaster dev;
- if (!dev) {
- LOG(ERROR) << "Failed to initiate keymaster session";
- return KeymasterSignResult::error;
- }
- if (!key_blob || !object || !signature_buffer || !signature_buffer_size) {
- LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument";
- return KeymasterSignResult::error;
- }
-
- km::AuthorizationSet outParams;
- std::string key(reinterpret_cast<const char*>(key_blob), key_blob_size);
- std::string input(reinterpret_cast<const char*>(object), object_size);
- std::string output;
- KeymasterOperation op;
-
- auto paramBuilder = km::AuthorizationSetBuilder().NoDigestOrPadding();
- while (true) {
- op = dev.begin(km::KeyPurpose::SIGN, key, paramBuilder, km::HardwareAuthToken(), &outParams);
- if (op.errorCode() == km::ErrorCode::KEY_RATE_LIMIT_EXCEEDED) {
- sleep(ratelimit);
- continue;
- } else
- break;
- }
-
- if (op.errorCode() == km::ErrorCode::KEY_REQUIRES_UPGRADE) {
- LOG(ERROR) << "Keymaster key requires upgrade";
- return KeymasterSignResult::upgrade;
- }
-
- if (op.errorCode() != km::ErrorCode::OK) {
- LOG(ERROR) << "Error starting keymaster signature transaction: " << int32_t(op.errorCode());
- return KeymasterSignResult::error;
- }
-
- if (!op.updateCompletely(input, &output)) {
- LOG(ERROR) << "Error sending data to keymaster signature transaction: "
- << uint32_t(op.errorCode());
- return KeymasterSignResult::error;
- }
-
- if (!op.finish(&output)) {
- LOG(ERROR) << "Error finalizing keymaster signature transaction: "
- << int32_t(op.errorCode());
- return KeymasterSignResult::error;
- }
-
- *signature_buffer = reinterpret_cast<uint8_t*>(malloc(output.size()));
- if (*signature_buffer == nullptr) {
- LOG(ERROR) << "Error allocation buffer for keymaster signature";
- return KeymasterSignResult::error;
- }
- *signature_buffer_size = output.size();
- std::copy(output.data(), output.data() + output.size(), *signature_buffer);
- return KeymasterSignResult::ok;
-}
diff --git a/crypto/fscrypt/Keymaster.h b/crypto/fscrypt/Keymaster.h
deleted file mode 100644
index 6f74db4..0000000
--- a/crypto/fscrypt/Keymaster.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_VOLD_KEYMASTER_H
-#define ANDROID_VOLD_KEYMASTER_H
-
-#include "KeyBuffer.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include <android-base/macros.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <keymasterV4_1/authorization_set.h>
-
-namespace km {
-
-using namespace ::android::hardware::keymaster::V4_1;
-
-// Surprisingly -- to me, at least -- this is totally fine. You can re-define symbols that were
-// brought in via a using directive (the "using namespace") above. In general this seems like a
-// dangerous thing to rely on, but in this case its implications are simple and straightforward:
-// km::ErrorCode refers to the 4.0 ErrorCode, though we pull everything else from 4.1.
-using ErrorCode = ::android::hardware::keymaster::V4_0::ErrorCode;
-using V4_1_ErrorCode = ::android::hardware::keymaster::V4_1::ErrorCode;
-
-} // namespace km
-
-using KmDevice = km::support::Keymaster;
-
-// C++ wrappers to the Keymaster hidl interface.
-// This is tailored to the needs of KeyStorage, but could be extended to be
-// a more general interface.
-
-// Wrapper for a Keymaster operation handle representing an
-// ongoing Keymaster operation. Aborts the operation
-// in the destructor if it is unfinished. Methods log failures
-// to LOG(ERROR).
-class KeymasterOperation {
- public:
- ~KeymasterOperation();
- // Is this instance valid? This is false if creation fails, and becomes
- // false on finish or if an update fails.
- explicit operator bool() const { return mError == km::ErrorCode::OK; }
- km::ErrorCode errorCode() const { return mError; }
- // Call "update" repeatedly until all of the input is consumed, and
- // concatenate the output. Return true on success.
- template <class TI, class TO>
- bool updateCompletely(TI& input, TO* output) {
- if (output) output->clear();
- return updateCompletely(input.data(), input.size(), [&](const char* b, size_t n) {
- if (output) std::copy(b, b + n, std::back_inserter(*output));
- });
- }
-
- // Finish and write the output to this string, unless pointer is null.
- bool finish(std::string* output);
- // Move constructor
- KeymasterOperation(KeymasterOperation&& rhs) { *this = std::move(rhs); }
- // Construct an object in an error state for error returns
- KeymasterOperation() : mDevice{nullptr}, mOpHandle{0}, mError{km::ErrorCode::UNKNOWN_ERROR} {}
- // Move Assignment
- KeymasterOperation& operator=(KeymasterOperation&& rhs) {
- mDevice = rhs.mDevice;
- rhs.mDevice = nullptr;
-
- mOpHandle = rhs.mOpHandle;
- rhs.mOpHandle = 0;
-
- mError = rhs.mError;
- rhs.mError = km::ErrorCode::UNKNOWN_ERROR;
-
- return *this;
- }
-
- private:
- KeymasterOperation(KmDevice* d, uint64_t h)
- : mDevice{d}, mOpHandle{h}, mError{km::ErrorCode::OK} {}
- KeymasterOperation(km::ErrorCode error) : mDevice{nullptr}, mOpHandle{0}, mError{error} {}
-
- bool updateCompletely(const char* input, size_t inputLen,
- const std::function<void(const char*, size_t)> consumer);
-
- KmDevice* mDevice;
- uint64_t mOpHandle;
- km::ErrorCode mError;
- DISALLOW_COPY_AND_ASSIGN(KeymasterOperation);
- friend class Keymaster;
-};
-
-// Wrapper for a Keymaster device for methods that start a KeymasterOperation or are not
-// part of one.
-class Keymaster {
- public:
- Keymaster();
- // false if we failed to open the keymaster device.
- explicit operator bool() { return mDevice.get() != nullptr; }
- // Generate a key in the keymaster from the given params.
- bool generateKey(const km::AuthorizationSet& inParams, std::string* key);
- // Exports a keymaster key with STORAGE_KEY tag wrapped with a per-boot ephemeral key
- km::ErrorCode exportKey(const KeyBuffer& kmKey, std::string* key);
- // If the keymaster supports it, permanently delete a key.
- bool deleteKey(const std::string& key);
- // Replace stored key blob in response to KM_ERROR_KEY_REQUIRES_UPGRADE.
- bool upgradeKey(const std::string& oldKey, const km::AuthorizationSet& inParams,
- std::string* newKey);
- // Begin a new cryptographic operation, collecting output parameters if pointer is non-null
- KeymasterOperation begin(km::KeyPurpose purpose, const std::string& key,
- const km::AuthorizationSet& inParams,
- const km::HardwareAuthToken& authToken,
- km::AuthorizationSet* outParams);
- bool isSecure();
-
- // Tell all Keymaster instances that early boot has ended and early boot-only keys can no longer
- // be created or used.
- static void earlyBootEnded();
-
- private:
- android::sp<KmDevice> mDevice;
- DISALLOW_COPY_AND_ASSIGN(Keymaster);
- static bool hmacKeyGenerated;
-};
-
-// FIXME no longer needed now cryptfs is in C++.
-
-/*
- * The following functions provide C bindings to keymaster services
- * needed by cryptfs scrypt. The compatibility check checks whether
- * the keymaster implementation is considered secure, i.e., TEE backed.
- * The create_key function generates an RSA key for signing.
- * The sign_object function signes an object with the given keymaster
- * key.
- */
-
-/* Return values for keymaster_sign_object_for_cryptfs_scrypt */
-
-enum class KeymasterSignResult {
- ok = 0,
- error = -1,
- upgrade = -2,
-};
-
-int keymaster_compatibility_cryptfs_scrypt();
-int keymaster_create_key_for_cryptfs_scrypt(uint32_t rsa_key_size, uint64_t rsa_exponent,
- uint32_t ratelimit, uint8_t* key_buffer,
- uint32_t key_buffer_size, uint32_t* key_out_size);
-
-int keymaster_upgrade_key_for_cryptfs_scrypt(uint32_t rsa_key_size, uint64_t rsa_exponent,
- uint32_t ratelimit, const uint8_t* key_blob,
- size_t key_blob_size, uint8_t* key_buffer,
- uint32_t key_buffer_size, uint32_t* key_out_size);
-
-KeymasterSignResult keymaster_sign_object_for_cryptfs_scrypt(
- const uint8_t* key_blob, size_t key_blob_size, uint32_t ratelimit, const uint8_t* object,
- const size_t object_size, uint8_t** signature_buffer, size_t* signature_buffer_size);
-
-#endif
diff --git a/crypto/fscrypt/MetadataCrypt.cpp b/crypto/fscrypt/MetadataCrypt.cpp
deleted file mode 100755
index 853e81e..0000000
--- a/crypto/fscrypt/MetadataCrypt.cpp
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright (C) 2016 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 "MetadataCrypt.h"
-#include "KeyBuffer.h"
-
-#include <algorithm>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include <fcntl.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <cutils/fs.h>
-#include <fs_mgr.h>
-#include <libdm/dm.h>
-
-#include "Checkpoint.h"
-#include "CryptoType.h"
-#include "EncryptInplace.h"
-#include "FsCrypt.h"
-#include "KeyStorage.h"
-#include "KeyUtil.h"
-#include "Keymaster.h"
-#include "Utils.h"
-#include "VoldUtil.h"
-
-#define TABLE_LOAD_RETRIES 10
-
-
-using android::fs_mgr::FstabEntry;
-using android::fs_mgr::GetEntryForMountPoint;
-using ::KeyBuffer;
-using namespace android::dm;
-
-// Parsed from metadata options
-struct CryptoOptions {
- struct CryptoType cipher = invalid_crypto_type;
- bool use_legacy_options_format = false;
- bool set_dun = true; // Non-legacy driver always sets DUN
- bool use_hw_wrapped_key = false;
-};
-
-static const std::string kDmNameUserdata = "userdata";
-
-static const char* kFn_keymaster_key_blob = "keymaster_key_blob";
-static const char* kFn_keymaster_key_blob_upgraded = "keymaster_key_blob_upgraded";
-
-// The first entry in this table is the default crypto type.
-constexpr CryptoType supported_crypto_types[] = {aes_256_xts, adiantum};
-
-static_assert(validateSupportedCryptoTypes(64, supported_crypto_types,
- array_length(supported_crypto_types)),
- "We have a CryptoType which was incompletely constructed.");
-
-constexpr CryptoType legacy_aes_256_xts =
- CryptoType().set_config_name("aes-256-xts").set_kernel_name("AES-256-XTS").set_keysize(64);
-
-static_assert(isValidCryptoType(64, legacy_aes_256_xts),
- "We have a CryptoType which was incompletely constructed.");
-
-// Returns KeyGeneration suitable for key as described in CryptoOptions
-const KeyGeneration makeGen(const CryptoOptions& options) {
- return KeyGeneration{options.cipher.get_keysize(), true, options.use_hw_wrapped_key};
-}
-
-static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
- // We're about to mount data not verified by verified boot. Tell Keymaster instances that early
- // boot has ended.
- ::Keymaster::earlyBootEnded();
-
- // fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
- // partitions in the fsck domain.
- if (setexeccon(::sFsckContext)) {
- PLOG(ERROR) << "Failed to setexeccon";
- return false;
- }
-
- if (fstab_default.empty()) {
- if (!ReadDefaultFstab(&fstab_default)) {
- PLOG(ERROR) << "Failed to open default fstab";
- return -1;
- }
- }
- auto mount_rc = fs_mgr_do_mount(&fstab_default, const_cast<char*>(mount_point),
- const_cast<char*>(blk_device), nullptr,
- ::cp_needsCheckpoint(), true);
- if (setexeccon(nullptr)) {
- PLOG(ERROR) << "Failed to clear setexeccon";
- return false;
- }
- if (mount_rc != 0) {
- LOG(ERROR) << "fs_mgr_do_mount failed with rc " << mount_rc;
- return false;
- }
- LOG(INFO) << "mount_via_fs_mgr::Mounted " << mount_point;
- return true;
-}
-
-// Note: It is possible to orphan a key if it is removed before deleting
-// Update this once keymaster APIs change, and we have a proper commit.
-static void commit_key(const std::string& dir) {
- while (!android::base::WaitForProperty("vold.checkpoint_committed", "1")) {
- LOG(ERROR) << "Wait for boot timed out";
- }
- Keymaster keymaster;
- auto keyPath = dir + "/" + kFn_keymaster_key_blob;
- auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
- std::string key;
-
- if (!android::base::ReadFileToString(keyPath, &key)) {
- LOG(ERROR) << "Failed to read old key: " << dir;
- return;
- }
- if (rename(newKeyPath.c_str(), keyPath.c_str()) != 0) {
- PLOG(ERROR) << "Unable to move upgraded key to location: " << keyPath;
- return;
- }
- if (!keymaster.deleteKey(key)) {
- LOG(ERROR) << "Key deletion failed during upgrade, continuing anyway: " << dir;
- }
- LOG(INFO) << "Old Key deleted: " << dir;
-}
-
-static bool read_key(const std::string& metadata_key_dir, const KeyGeneration& gen,
- KeyBuffer* key) {
- if (metadata_key_dir.empty()) {
- LOG(ERROR) << "Failed to get metadata_key_dir";
- return false;
- }
- std::string sKey;
- auto dir = metadata_key_dir + "/key";
- LOG(INFO) << "metadata_key_dir/key: " << dir;
- if (fs_mkdirs(dir.c_str(), 0700)) {
- PLOG(ERROR) << "Creating directories: " << dir;
- return false;
- }
- auto temp = metadata_key_dir + "/tmp";
- auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
- /* If we have a leftover upgraded key, delete it.
- * We either failed an update and must return to the old key,
- * or we rebooted before commiting the keys in a freak accident.
- * Either way, we can re-upgrade the key if we need to.
- */
-
- Keymaster keymaster;
- if (pathExists(newKeyPath)) {
- if (!android::base::ReadFileToString(newKeyPath, &sKey))
- LOG(ERROR) << "Failed to read incomplete key: " << dir;
- else if (!keymaster.deleteKey(sKey))
- LOG(ERROR) << "Incomplete key deletion failed, continuing anyway: " << dir;
- else
- unlink(newKeyPath.c_str());
- }
- bool needs_cp = cp_needsCheckpoint();
- if (!retrieveOrGenerateKey(dir, temp, kEmptyAuthentication, gen, key, true)) return false;
- if (needs_cp && pathExists(newKeyPath)) std::thread(commit_key, dir).detach();
- return true;
-}
-
-static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_sec) {
- if (::GetBlockDev512Sectors(real_blkdev, nr_sec) != android::OK) {
- PLOG(ERROR) << "Unable to measure size of " << real_blkdev;
- return false;
- }
- return true;
-}
-
-static bool create_crypto_blk_dev(const std::string& dm_name, const std::string& blk_device,
- const KeyBuffer& key, const CryptoOptions& options,
- std::string* crypto_blkdev, uint64_t* nr_sec) {
- if (!get_number_of_sectors(blk_device, nr_sec)) return false;
- // TODO(paulcrowley): don't hardcode that DmTargetDefaultKey uses 4096-byte
- // sectors
- *nr_sec &= ~7;
-
- KeyBuffer module_key;
- if (options.use_hw_wrapped_key) {
- if (!exportWrappedStorageKey(key, &module_key)) {
- LOG(ERROR) << "Failed to get ephemeral wrapped key";
- return false;
- }
- } else {
- module_key = key;
- }
-
- KeyBuffer hex_key_buffer;
- if (::StrToHex(module_key, hex_key_buffer) != android::OK) {
- LOG(ERROR) << "Failed to turn key to hex";
- return false;
- }
- std::string hex_key(hex_key_buffer.data(), hex_key_buffer.size());
-
- auto target = std::make_unique<DmTargetDefaultKey>(0, *nr_sec, options.cipher.get_kernel_name(),
- hex_key, blk_device, 0);
- if (options.use_legacy_options_format) target->SetUseLegacyOptionsFormat();
- if (options.set_dun) target->SetSetDun();
- if (options.use_hw_wrapped_key) target->SetWrappedKeyV0();
-
- DmTable table;
- table.AddTarget(std::move(target));
-
- auto& dm = DeviceMapper::Instance();
- for (int i = 0;; i++) {
- if (dm.CreateDevice(dm_name, table)) {
- break;
- }
- if (i + 1 >= TABLE_LOAD_RETRIES) {
- PLOG(ERROR) << "Could not create default-key device " << dm_name;
- return false;
- }
- PLOG(INFO) << "Could not create default-key device, retrying";
- usleep(500000);
- }
-
- if (!dm.GetDmDevicePathByName(dm_name, crypto_blkdev)) {
- LOG(ERROR) << "Cannot retrieve default-key device status " << dm_name;
- return false;
- }
- std::stringstream ss;
- ss << *crypto_blkdev;
- LOG(INFO) << "Created device: " << ss.str();
- return true;
-}
-
-static const CryptoType& lookup_cipher(const std::string& cipher_name) {
- if (cipher_name.empty()) return supported_crypto_types[0];
- for (size_t i = 0; i < array_length(supported_crypto_types); i++) {
- if (cipher_name == supported_crypto_types[i].get_config_name()) {
- return supported_crypto_types[i];
- }
- }
- return invalid_crypto_type;
-}
-
-static bool parse_options(const std::string& options_string, CryptoOptions* options) {
- auto parts = android::base::Split(options_string, ":");
- if (parts.size() < 1 || parts.size() > 2) {
- LOG(ERROR) << "Invalid metadata encryption option: " << options_string;
- return false;
- }
- std::string cipher_name = parts[0];
- options->cipher = lookup_cipher(cipher_name);
- if (options->cipher.get_kernel_name() == nullptr) {
- LOG(ERROR) << "No metadata cipher named " << cipher_name << " found";
- return false;
- }
-
- if (parts.size() == 2) {
- if (parts[1] == "wrappedkey_v0") {
- options->use_hw_wrapped_key = true;
- } else {
- LOG(ERROR) << "Invalid metadata encryption flag: " << parts[1];
- return false;
- }
- }
- return true;
-}
-
-bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::string& mount_point,
- bool needs_encrypt) {
- LOG(INFO) << "fscrypt_mount_metadata_encrypted: " << mount_point << " " << needs_encrypt;
- auto encrypted_state = android::base::GetProperty("ro.crypto.state", "");
- if (encrypted_state != "" && encrypted_state != "encrypted") {
- LOG(ERROR) << "fscrypt_enable_crypto got unexpected starting state: " << encrypted_state;
- return false;
- }
- if (fstab_default.empty()) {
- if (!ReadDefaultFstab(&fstab_default)) {
- PLOG(ERROR) << "Failed to open default fstab";
- return -1;
- }
- }
- auto data_rec = GetEntryForMountPoint(&fstab_default, mount_point);
- if (!data_rec) {
- LOG(ERROR) << "Failed to get data_rec for " << mount_point;
- return false;
- }
-
- constexpr unsigned int pre_gki_level = 29;
- unsigned int options_format_version = android::base::GetUintProperty<unsigned int>(
- "ro.crypto.dm_default_key.options_format.version",
- (GetFirstApiLevel() <= pre_gki_level ? 1 : 2));
-
- CryptoOptions options;
- if (options_format_version == 1) {
- if (!data_rec->metadata_encryption.empty()) {
- LOG(ERROR) << "metadata_encryption options cannot be set in legacy mode";
- return false;
- }
- options.cipher = legacy_aes_256_xts;
- options.use_legacy_options_format = true;
- if (is_metadata_wrapped_key_supported()) {
- options.use_hw_wrapped_key = true;
- LOG(INFO) << "metadata_wrapped_key_true";
- }
- options.set_dun = android::base::GetBoolProperty("ro.crypto.set_dun", false);
- if (!options.set_dun && data_rec->fs_mgr_flags.checkpoint_blk) {
- LOG(ERROR)
- << "Block checkpoints and metadata encryption require ro.crypto.set_dun option";
- return false;
- }
- } else if (options_format_version == 2) {
- if (!parse_options(data_rec->metadata_encryption, &options)) return false;
- } else {
- LOG(ERROR) << "Unknown options_format_version: " << options_format_version;
- return false;
- }
- auto gen = needs_encrypt ? makeGen(options) : neverGen();
- KeyBuffer key;
- if (!read_key(data_rec->metadata_key_dir, gen, &key)) return false;
-
- std::string crypto_blkdev;
- uint64_t nr_sec;
- if (!create_crypto_blk_dev(kDmNameUserdata, blk_device, key, options, &crypto_blkdev, &nr_sec))
- return false;
-
- // FIXME handle the corrupt case
- if (needs_encrypt) {
- LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec;
- off64_t size_already_done = 0;
- auto rc = cryptfs_enable_inplace(crypto_blkdev.data(), blk_device.data(), nr_sec,
- &size_already_done, nr_sec, 0, false);
- if (rc != 0) {
- LOG(ERROR) << "Inplace crypto failed with code: " << rc;
- return false;
- }
- if (static_cast<uint64_t>(size_already_done) != nr_sec) {
- LOG(ERROR) << "Inplace crypto only got up to sector: " << size_already_done;
- return false;
- }
- LOG(INFO) << "Inplace encryption complete";
- }
-
- LOG(INFO) << "Mounting metadata-encrypted filesystem:" << mount_point;
- mount_via_fs_mgr(mount_point.c_str(), crypto_blkdev.c_str());
- android::base::SetProperty("ro.crypto.fs_crypto_blkdev", crypto_blkdev);
-
- // Record that there's at least one fstab entry with metadata encryption
- if (!android::base::SetProperty("ro.crypto.metadata.enabled", "true")) {
- LOG(WARNING) << "failed to set ro.crypto.metadata.enabled"; // This isn't fatal
- }
- return true;
-}
-
-static bool get_volume_options(CryptoOptions* options) {
- return parse_options(android::base::GetProperty("ro.crypto.volume.metadata.encryption", ""),
- options);
-}
-
-bool defaultkey_volume_keygen(KeyGeneration* gen) {
- CryptoOptions options;
- if (!get_volume_options(&options)) return false;
- *gen = makeGen(options);
- return true;
-}
-
-bool defaultkey_setup_ext_volume(const std::string& label, const std::string& blk_device,
- const KeyBuffer& key, std::string* out_crypto_blkdev) {
- LOG(ERROR) << "defaultkey_setup_ext_volume: " << label << " " << blk_device;
-
- CryptoOptions options;
- if (!get_volume_options(&options)) return false;
- uint64_t nr_sec;
- return create_crypto_blk_dev(label, blk_device, key, options, out_crypto_blkdev, &nr_sec);
-}
diff --git a/crypto/fscrypt/MetadataCrypt.h b/crypto/fscrypt/MetadataCrypt.h
deleted file mode 100644
index 0370664..0000000
--- a/crypto/fscrypt/MetadataCrypt.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2016 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 _METADATA_CRYPT_H
-#define _METADATA_CRYPT_H
-
-#include <string>
-
-#include "KeyBuffer.h"
-#include "KeyUtil.h"
-
-
-bool fscrypt_mount_metadata_encrypted(const std::string& block_device,
- const std::string& mount_point, bool needs_encrypt);
-
-bool defaultkey_volume_keygen(KeyGeneration* gen);
-
-bool defaultkey_setup_ext_volume(const std::string& label, const std::string& blk_device,
- const KeyBuffer& key,
- std::string* out_crypto_blkdev);
-
-#endif
diff --git a/crypto/fscrypt/Process.cpp b/crypto/fscrypt/Process.cpp
deleted file mode 100644
index 277d6a3..0000000
--- a/crypto/fscrypt/Process.cpp
+++ /dev/null
@@ -1,180 +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 <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <fts.h>
-#include <poll.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <fstream>
-#include <mntent.h>
-#include <unordered_set>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/parseint.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-
-#include "Process.h"
-
-using android::base::StringPrintf;
-
-namespace android {
-namespace vold {
-
-static bool checkMaps(const std::string& path, const std::string& prefix) {
- bool found = false;
- auto file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
- if (!file) {
- return false;
- }
-
- char* buf = nullptr;
- size_t len = 0;
- while (getline(&buf, &len, file.get()) != -1) {
- std::string line(buf);
- std::string::size_type pos = line.find('/');
- if (pos != std::string::npos) {
- line = line.substr(pos);
- if (android::base::StartsWith(line, prefix)) {
- LOG(WARNING) << "Found map " << path << " referencing " << line;
- found = true;
- break;
- }
- }
- }
- free(buf);
-
- return found;
-}
-
-static bool checkSymlink(const std::string& path, const std::string& prefix) {
- std::string res;
- if (android::base::Readlink(path, &res)) {
- if (android::base::StartsWith(res, prefix)) {
- LOG(WARNING) << "Found symlink " << path << " referencing " << res;
- return true;
- }
- }
- return false;
-}
-
-// TODO: Refactor the code with KillProcessesWithOpenFiles().
-int KillProcessesWithMounts(const std::string& prefix, int signal) {
- std::unordered_set<pid_t> pids;
-
- auto proc_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/proc"), closedir);
- if (!proc_d) {
- PLOG(ERROR) << "Failed to open proc";
- return -1;
- }
-
- struct dirent* proc_de;
- while ((proc_de = readdir(proc_d.get())) != nullptr) {
- // We only care about valid PIDs
- pid_t pid;
- if (proc_de->d_type != DT_DIR) continue;
- if (!android::base::ParseInt(proc_de->d_name, &pid)) continue;
-
- // Look for references to prefix
- std::string mounts_file(StringPrintf("/proc/%d/mounts", pid));
- auto fp = std::unique_ptr<FILE, int (*)(FILE*)>(
- setmntent(mounts_file.c_str(), "r"), endmntent);
- if (!fp) {
- PLOG(WARNING) << "Failed to open " << mounts_file;
- continue;
- }
-
- // Check if obb directory is mounted, and get all packages of mounted app data directory.
- mntent* mentry;
- while ((mentry = getmntent(fp.get())) != nullptr) {
- if (android::base::StartsWith(mentry->mnt_dir, prefix)) {
- pids.insert(pid);
- break;
- }
- }
- }
- if (signal != 0) {
- for (const auto& pid : pids) {
- LOG(WARNING) << "Killing pid "<< pid << " with signal " << strsignal(signal) <<
- " because it has a mount with prefix " << prefix;
- kill(pid, signal);
- }
- }
- return pids.size();
-}
-
-int KillProcessesWithOpenFiles(const std::string& prefix, int signal) {
- std::unordered_set<pid_t> pids;
-
- auto proc_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/proc"), closedir);
- if (!proc_d) {
- PLOG(ERROR) << "Failed to open proc";
- return -1;
- }
-
- struct dirent* proc_de;
- while ((proc_de = readdir(proc_d.get())) != nullptr) {
- // We only care about valid PIDs
- pid_t pid;
- if (proc_de->d_type != DT_DIR) continue;
- if (!android::base::ParseInt(proc_de->d_name, &pid)) continue;
-
- // Look for references to prefix
- bool found = false;
- auto path = StringPrintf("/proc/%d", pid);
- found |= checkMaps(path + "/maps", prefix);
- found |= checkSymlink(path + "/cwd", prefix);
- found |= checkSymlink(path + "/root", prefix);
- found |= checkSymlink(path + "/exe", prefix);
-
- auto fd_path = path + "/fd";
- auto fd_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(fd_path.c_str()), closedir);
- if (!fd_d) {
- PLOG(WARNING) << "Failed to open " << fd_path;
- } else {
- struct dirent* fd_de;
- while ((fd_de = readdir(fd_d.get())) != nullptr) {
- if (fd_de->d_type != DT_LNK) continue;
- found |= checkSymlink(fd_path + "/" + fd_de->d_name, prefix);
- }
- }
-
- if (found) {
- pids.insert(pid);
- }
- }
- if (signal != 0) {
- for (const auto& pid : pids) {
- LOG(WARNING) << "Sending " << strsignal(signal) << " to " << pid;
- kill(pid, signal);
- }
- }
- return pids.size();
-}
-
-} // namespace vold
-} // namespace android
diff --git a/crypto/fscrypt/Process.h b/crypto/fscrypt/Process.h
deleted file mode 100644
index 1c59812..0000000
--- a/crypto/fscrypt/Process.h
+++ /dev/null
@@ -1,29 +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.
- */
-
-#ifndef _PROCESS_H
-#define _PROCESS_H
-
-namespace android {
-namespace vold {
-
-int KillProcessesWithOpenFiles(const std::string& path, int signal);
-int KillProcessesWithMounts(const std::string& path, int signal);
-
-} // namespace vold
-} // namespace android
-
-#endif
diff --git a/crypto/fscrypt/ScryptParameters.cpp b/crypto/fscrypt/ScryptParameters.cpp
deleted file mode 100644
index 669809b..0000000
--- a/crypto/fscrypt/ScryptParameters.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2016 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 "ScryptParameters.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-bool parse_scrypt_parameters(const char* paramstr, int *Nf, int *rf, int *pf) {
- int params[3];
- char *token;
- char *saveptr;
- int i;
-
- /*
- * 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(const_cast<char *>(paramstr), ":", &saveptr);
- token != nullptr && i < 3;
- i++, token = strtok_r(nullptr, ":", &saveptr)) {
- char *endptr;
- params[i] = strtol(token, &endptr, 10);
-
- /*
- * Check that there was a valid number and it's 8-bit.
- */
- if ((*token == '\0') || (*endptr != '\0') || params[i] < 0 || params[i] > 255) {
- return false;
- }
- }
- if (token != nullptr) {
- return false;
- }
- *Nf = params[0]; *rf = params[1]; *pf = params[2];
- return true;
-}
diff --git a/crypto/fscrypt/ScryptParameters.h b/crypto/fscrypt/ScryptParameters.h
deleted file mode 100644
index 1b43ea5..0000000
--- a/crypto/fscrypt/ScryptParameters.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_VOLD_SCRYPT_PARAMETERS_H
-#define ANDROID_VOLD_SCRYPT_PARAMETERS_H
-
-#include <stdbool.h>
-#include <sys/cdefs.h>
-
-#define SCRYPT_PROP "ro.crypto.scrypt_params"
-#define SCRYPT_DEFAULTS "15:3:1"
-
-__BEGIN_DECLS
-
-bool parse_scrypt_parameters(const char* paramstr, int *Nf, int *rf, int *pf);
-
-__END_DECLS
-
-#endif
diff --git a/crypto/fscrypt/Utils.cpp b/crypto/fscrypt/Utils.cpp
deleted file mode 100755
index 3b0eda0..0000000
--- a/crypto/fscrypt/Utils.cpp
+++ /dev/null
@@ -1,1622 +0,0 @@
-/*
- * Copyright (C) 2015 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 "Utils.h"
-
-#include "Process.h"
-#include "sehandle.h"
-
-#include <android-base/chrono_utils.h>
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <cutils/fs.h>
-#include <logwrap/logwrap.h>
-#include <private/android_filesystem_config.h>
-#include <private/android_projectid_config.h>
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <linux/fs.h>
-#include <linux/posix_acl.h>
-#include <linux/posix_acl_xattr.h>
-#include <mntent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <sys/sysmacros.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/xattr.h>
-#include <unistd.h>
-
-#include <filesystem>
-#include <list>
-#include <mutex>
-#include <regex>
-#include <thread>
-
-#ifndef UMOUNT_NOFOLLOW
-#define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */
-#endif
-
-using namespace std::chrono_literals;
-using android::base::EndsWith;
-using android::base::ReadFileToString;
-using android::base::StartsWith;
-using android::base::StringPrintf;
-using android::base::unique_fd;
-
-struct selabel_handle* sehandle;
-
-security_context_t sBlkidContext = nullptr;
-security_context_t sBlkidUntrustedContext = nullptr;
-security_context_t sFsckContext = nullptr;
-security_context_t sFsckUntrustedContext = nullptr;
-
-bool sSleepOnUnmount = true;
-
-static const char* kBlkidPath = "/system/bin/blkid";
-static const char* kKeyPath = "/data/misc/vold";
-
-static const char* kProcDevices = "/proc/devices";
-static const char* kProcFilesystems = "/proc/filesystems";
-
-static const char* kAndroidDir = "/Android/";
-static const char* kAppDataDir = "/Android/data/";
-static const char* kAppMediaDir = "/Android/media/";
-static const char* kAppObbDir = "/Android/obb/";
-
-static const char* kMediaProviderCtx = "u:r:mediaprovider:";
-static const char* kMediaProviderAppCtx = "u:r:mediaprovider_app:";
-
-// Lock used to protect process-level SELinux changes from racing with each
-// other between multiple threads.
-static std::mutex kSecurityLock;
-
-std::string GetFuseMountPathForUser(userid_t user_id, const std::string& relative_upper_path) {
- return StringPrintf("/mnt/user/%d/%s", user_id, relative_upper_path.c_str());
-}
-
-android::status_t CreateDeviceNode(const std::string& path, dev_t dev) {
- std::lock_guard<std::mutex> lock(kSecurityLock);
- const char* cpath = path.c_str();
- android::status_t res = 0;
-
- char* secontext = nullptr;
- if (sehandle) {
- if (!selabel_lookup(sehandle, &secontext, cpath, S_IFBLK)) {
- setfscreatecon(secontext);
- }
- }
-
- mode_t mode = 0660 | S_IFBLK;
- if (mknod(cpath, mode, dev) < 0) {
- if (errno != EEXIST) {
- PLOG(ERROR) << "Failed to create device node for " << major(dev) << ":" << minor(dev)
- << " at " << path;
- res = -errno;
- }
- }
-
- if (secontext) {
- setfscreatecon(nullptr);
- freecon(secontext);
- }
-
- return res;
-}
-
-android::status_t DestroyDeviceNode(const std::string& path) {
- const char* cpath = path.c_str();
- if (TEMP_FAILURE_RETRY(unlink(cpath))) {
- return -errno;
- } else {
- return android::OK;
- }
-}
-
-// Sets a default ACL on the directory.
-int SetDefaultAcl(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
- std::vector<gid_t> additionalGids) {
- if (IsSdcardfsUsed()) {
- // sdcardfs magically takes care of this
- return android::OK;
- }
-
- size_t num_entries = 3 + (additionalGids.size() > 0 ? additionalGids.size() + 1 : 0);
- size_t size = sizeof(posix_acl_xattr_header) + num_entries * sizeof(posix_acl_xattr_entry);
- auto buf = std::make_unique<uint8_t[]>(size);
-
- posix_acl_xattr_header* acl_header = reinterpret_cast<posix_acl_xattr_header*>(buf.get());
- acl_header->a_version = POSIX_ACL_XATTR_VERSION;
-
- posix_acl_xattr_entry* entry =
- reinterpret_cast<posix_acl_xattr_entry*>(buf.get() + sizeof(posix_acl_xattr_header));
-
- int tag_index = 0;
-
- entry[tag_index].e_tag = ACL_USER_OBJ;
- // The existing mode_t mask has the ACL in the lower 9 bits:
- // the lowest 3 for "other", the next 3 the group, the next 3 for the owner
- // Use the mode_t masks to get these bits out, and shift them to get the
- // correct value per entity.
- //
- // Eg if mode_t = 0700, rwx for the owner, then & S_IRWXU >> 6 results in 7
- entry[tag_index].e_perm = (mode & S_IRWXU) >> 6;
- entry[tag_index].e_id = uid;
- tag_index++;
-
- entry[tag_index].e_tag = ACL_GROUP_OBJ;
- entry[tag_index].e_perm = (mode & S_IRWXG) >> 3;
- entry[tag_index].e_id = gid;
- tag_index++;
-
- if (additionalGids.size() > 0) {
- for (gid_t additional_gid : additionalGids) {
- entry[tag_index].e_tag = ACL_GROUP;
- entry[tag_index].e_perm = (mode & S_IRWXG) >> 3;
- entry[tag_index].e_id = additional_gid;
- tag_index++;
- }
-
- entry[tag_index].e_tag = ACL_MASK;
- entry[tag_index].e_perm = (mode & S_IRWXG) >> 3;
- entry[tag_index].e_id = 0;
- tag_index++;
- }
-
- entry[tag_index].e_tag = ACL_OTHER;
- entry[tag_index].e_perm = mode & S_IRWXO;
- entry[tag_index].e_id = 0;
-
- int ret = setxattr(path.c_str(), XATTR_NAME_POSIX_ACL_DEFAULT, acl_header, size, 0);
-
- if (ret != 0) {
- PLOG(ERROR) << "Failed to set default ACL on " << path;
- }
-
- return ret;
-}
-
-int SetQuotaInherit(const std::string& path) {
- unsigned long flags;
-
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open " << path << " to set project id inheritance.";
- return -1;
- }
-
- int ret = ioctl(fd, FS_IOC_GETFLAGS, &flags);
- if (ret == -1) {
- PLOG(ERROR) << "Failed to get flags for " << path << " to set project id inheritance.";
- return ret;
- }
-
- flags |= FS_PROJINHERIT_FL;
-
- ret = ioctl(fd, FS_IOC_SETFLAGS, &flags);
- if (ret == -1) {
- PLOG(ERROR) << "Failed to set flags for " << path << " to set project id inheritance.";
- return ret;
- }
-
- return 0;
-}
-
-int SetQuotaProjectId(const std::string& path, long projectId) {
- struct fsxattr fsx;
-
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open " << path << " to set project id.";
- return -1;
- }
-
- int ret = ioctl(fd, FS_IOC_FSGETXATTR, &fsx);
- if (ret == -1) {
- PLOG(ERROR) << "Failed to get extended attributes for " << path << " to get project id.";
- return ret;
- }
-
- fsx.fsx_projid = projectId;
- return ioctl(fd, FS_IOC_FSSETXATTR, &fsx);
-}
-
-int PrepareDirWithProjectId(const std::string& path, mode_t mode, uid_t uid, gid_t gid,
- long projectId) {
- int ret = fs_prepare_dir(path.c_str(), mode, uid, gid);
-
- if (ret != 0) {
- return ret;
- }
-
- if (!IsSdcardfsUsed()) {
- ret = SetQuotaProjectId(path, projectId);
- }
-
- return ret;
-}
-
-static int FixupAppDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid, long projectId) {
- namespace fs = std::filesystem;
-
- // Setup the directory itself correctly
- int ret = PrepareDirWithProjectId(path, mode, uid, gid, projectId);
- if (ret != android::OK) {
- return ret;
- }
-
- // Fixup all of its file entries
- for (const auto& itEntry : fs::directory_iterator(path)) {
- ret = lchown(itEntry.path().c_str(), uid, gid);
- if (ret != 0) {
- return ret;
- }
-
- ret = chmod(itEntry.path().c_str(), mode);
- if (ret != 0) {
- return ret;
- }
-
- if (!IsSdcardfsUsed()) {
- ret = SetQuotaProjectId(itEntry.path(), projectId);
- if (ret != 0) {
- return ret;
- }
- }
- }
-
- return android::OK;
-}
-
-int PrepareAppDirFromRoot(const std::string& path, const std::string& root, int appUid,
- bool fixupExisting) {
- long projectId;
- size_t pos;
- int ret = 0;
- bool sdcardfsSupport = IsSdcardfsUsed();
-
- // Make sure the Android/ directories exist and are setup correctly
- ret = PrepareAndroidDirs(root);
- if (ret != 0) {
- LOG(ERROR) << "Failed to prepare Android/ directories.";
- return ret;
- }
-
- // Now create the application-specific subdir(s)
- // path is something like /data/media/0/Android/data/com.foo/files
- // First, chop off the volume root, eg /data/media/0
- std::string pathFromRoot = path.substr(root.length());
-
- uid_t uid = appUid;
- gid_t gid = AID_MEDIA_RW;
- std::vector<gid_t> additionalGids;
- std::string appDir;
-
- // Check that the next part matches one of the allowed Android/ dirs
- if (StartsWith(pathFromRoot, kAppDataDir)) {
- appDir = kAppDataDir;
- if (!sdcardfsSupport) {
- gid = AID_EXT_DATA_RW;
- // Also add the app's own UID as a group; since apps belong to a group
- // that matches their UID, this ensures that they will always have access to
- // the files created in these dirs, even if they are created by other processes
- additionalGids.push_back(uid);
- }
- } else if (StartsWith(pathFromRoot, kAppMediaDir)) {
- appDir = kAppMediaDir;
- if (!sdcardfsSupport) {
- gid = AID_MEDIA_RW;
- }
- } else if (StartsWith(pathFromRoot, kAppObbDir)) {
- appDir = kAppObbDir;
- if (!sdcardfsSupport) {
- gid = AID_EXT_OBB_RW;
- // See comments for kAppDataDir above
- additionalGids.push_back(uid);
- }
- } else {
- LOG(ERROR) << "Invalid application directory: " << path;
- return -EINVAL;
- }
-
- // mode = 770, plus sticky bit on directory to inherit GID when apps
- // create subdirs
- mode_t mode = S_IRWXU | S_IRWXG | S_ISGID;
- // the project ID for application-specific directories is directly
- // derived from their uid
-
- // Chop off the generic application-specific part, eg /Android/data/
- // this leaves us with something like com.foo/files/
- std::string leftToCreate = pathFromRoot.substr(appDir.length());
- if (!EndsWith(leftToCreate, "/")) {
- leftToCreate += "/";
- }
- std::string pathToCreate = root + appDir;
- int depth = 0;
- // Derive initial project ID
- if (appDir == kAppDataDir || appDir == kAppMediaDir) {
- projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START;
- } else if (appDir == kAppObbDir) {
- projectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START;
- }
-
- while ((pos = leftToCreate.find('/')) != std::string::npos) {
- std::string component = leftToCreate.substr(0, pos + 1);
- leftToCreate = leftToCreate.erase(0, pos + 1);
- pathToCreate = pathToCreate + component;
-
- if (appDir == kAppDataDir && depth == 1 && component == "cache/") {
- // All dirs use the "app" project ID, except for the cache dirs in
- // Android/data, eg Android/data/com.foo/cache
- // Note that this "sticks" - eg subdirs of this dir need the same
- // project ID.
- projectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START;
- }
-
- if (fixupExisting && access(pathToCreate.c_str(), F_OK) == 0) {
- // Fixup all files in this existing directory with the correct UID/GID
- // and project ID.
- ret = FixupAppDir(pathToCreate, mode, uid, gid, projectId);
- } else {
- ret = PrepareDirWithProjectId(pathToCreate, mode, uid, gid, projectId);
- }
-
- if (ret != 0) {
- return ret;
- }
-
- if (depth == 0) {
- // Set the default ACL on the top-level application-specific directories,
- // to ensure that even if applications run with a umask of 0077,
- // new directories within these directories will allow the GID
- // specified here to write; this is necessary for apps like
- // installers and MTP, that require access here.
- //
- // See man (5) acl for more details.
- ret = SetDefaultAcl(pathToCreate, mode, uid, gid, additionalGids);
- if (ret != 0) {
- return ret;
- }
-
- if (!sdcardfsSupport) {
- // Set project ID inheritance, so that future subdirectories inherit the
- // same project ID
- ret = SetQuotaInherit(pathToCreate);
- if (ret != 0) {
- return ret;
- }
- }
- }
-
- depth++;
- }
-
- return android::OK;
-}
-
-android::status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
- std::lock_guard<std::mutex> lock(kSecurityLock);
- const char* cpath = path.c_str();
-
- char* secontext = nullptr;
- if (sehandle) {
- if (!selabel_lookup(sehandle, &secontext, cpath, S_IFDIR)) {
- setfscreatecon(secontext);
- }
- }
-
- int res = fs_prepare_dir(cpath, mode, uid, gid);
-
- if (secontext) {
- setfscreatecon(nullptr);
- freecon(secontext);
- }
-
- if (res == 0) {
- return android::OK;
- } else {
- return -errno;
- }
-}
-
-android::status_t ForceUnmount(const std::string& path) {
- const char* cpath = path.c_str();
- if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
- return android::OK;
- }
- // Apps might still be handling eject request, so wait before
- // we start sending signals
- if (sSleepOnUnmount) sleep(5);
-
- android::vold::KillProcessesWithOpenFiles(path, SIGINT);
- if (sSleepOnUnmount) sleep(5);
- if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
- return android::OK;
- }
-
- android::vold::KillProcessesWithOpenFiles(path, SIGTERM);
- if (sSleepOnUnmount) sleep(5);
- if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
- return android::OK;
- }
-
- android::vold::KillProcessesWithOpenFiles(path, SIGKILL);
- if (sSleepOnUnmount) sleep(5);
- if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
- return android::OK;
- }
- PLOG(INFO) << "ForceUnmount failed";
- return -errno;
-}
-
-android::status_t KillProcessesWithMountPrefix(const std::string& path) {
- if (android::vold::KillProcessesWithMounts(path, SIGINT) == 0) {
- return android::OK;
- }
- if (sSleepOnUnmount) sleep(5);
-
- if (android::vold::KillProcessesWithMounts(path, SIGTERM) == 0) {
- return android::OK;
- }
- if (sSleepOnUnmount) sleep(5);
-
- if (android::vold::KillProcessesWithMounts(path, SIGKILL) == 0) {
- return android::OK;
- }
- if (sSleepOnUnmount) sleep(5);
-
- // Send SIGKILL a second time to determine if we've
- // actually killed everyone mount
- if (android::vold::KillProcessesWithMounts(path, SIGKILL) == 0) {
- return android::OK;
- }
- PLOG(ERROR) << "Failed to kill processes using " << path;
- return -EBUSY;
-}
-
-android::status_t KillProcessesUsingPath(const std::string& path) {
- if (android::vold::KillProcessesWithOpenFiles(path, SIGINT) == 0) {
- return android::OK;
- }
- if (sSleepOnUnmount) sleep(5);
-
- if (android::vold::KillProcessesWithOpenFiles(path, SIGTERM) == 0) {
- return android::OK;
- }
- if (sSleepOnUnmount) sleep(5);
-
- if (android::vold::KillProcessesWithOpenFiles(path, SIGKILL) == 0) {
- return android::OK;
- }
- if (sSleepOnUnmount) sleep(5);
-
- // Send SIGKILL a second time to determine if we've
- // actually killed everyone with open files
- if (android::vold::KillProcessesWithOpenFiles(path, SIGKILL) == 0) {
- return android::OK;
- }
- PLOG(ERROR) << "Failed to kill processes using " << path;
- return -EBUSY;
-}
-
-android::status_t BindMount(const std::string& source, const std::string& target) {
- if (UnmountTree(target) < 0) {
- return -errno;
- }
- if (TEMP_FAILURE_RETRY(mount(source.c_str(), target.c_str(), nullptr, MS_BIND, nullptr)) < 0) {
- PLOG(ERROR) << "Failed to bind mount " << source << " to " << target;
- return -errno;
- }
- return android::OK;
-}
-
-android::status_t Symlink(const std::string& target, const std::string& linkpath) {
- if (Unlink(linkpath) < 0) {
- return -errno;
- }
- if (TEMP_FAILURE_RETRY(symlink(target.c_str(), linkpath.c_str())) < 0) {
- PLOG(ERROR) << "Failed to create symlink " << linkpath << " to " << target;
- return -errno;
- }
- return android::OK;
-}
-
-android::status_t Unlink(const std::string& linkpath) {
- if (TEMP_FAILURE_RETRY(unlink(linkpath.c_str())) < 0 && errno != EINVAL && errno != ENOENT) {
- PLOG(ERROR) << "Failed to unlink " << linkpath;
- return -errno;
- }
- return android::OK;
-}
-
-android::status_t CreateDir(const std::string& dir, mode_t mode) {
- struct stat sb;
- if (TEMP_FAILURE_RETRY(stat(dir.c_str(), &sb)) == 0) {
- if (S_ISDIR(sb.st_mode)) {
- return android::OK;
- } else if (TEMP_FAILURE_RETRY(unlink(dir.c_str())) == -1) {
- PLOG(ERROR) << "Failed to unlink " << dir;
- return -errno;
- }
- } else if (errno != ENOENT) {
- PLOG(ERROR) << "Failed to stat " << dir;
- return -errno;
- }
- if (TEMP_FAILURE_RETRY(mkdir(dir.c_str(), mode)) == -1 && errno != EEXIST) {
- PLOG(ERROR) << "Failed to mkdir " << dir;
- return -errno;
- }
- return android::OK;
-}
-
-bool FindValue(const std::string& raw, const std::string& key, std::string* value) {
- auto qual = key + "=\"";
- size_t start = 0;
- while (true) {
- start = raw.find(qual, start);
- if (start == std::string::npos) return false;
- if (start == 0 || raw[start - 1] == ' ') {
- break;
- }
- start += 1;
- }
- start += qual.length();
-
- auto end = raw.find("\"", start);
- if (end == std::string::npos) return false;
-
- *value = raw.substr(start, end - start);
- return true;
-}
-
-static android::status_t readMetadata(const std::string& path, std::string* fsType, std::string* fsUuid,
- std::string* fsLabel, bool untrusted) {
- fsType->clear();
- fsUuid->clear();
- fsLabel->clear();
-
- std::vector<std::string> cmd;
- cmd.push_back(kBlkidPath);
- cmd.push_back("-c");
- cmd.push_back("/dev/null");
- cmd.push_back("-s");
- cmd.push_back("TYPE");
- cmd.push_back("-s");
- cmd.push_back("UUID");
- cmd.push_back("-s");
- cmd.push_back("LABEL");
- cmd.push_back(path);
-
- std::vector<std::string> output;
- android::status_t res = ForkExecvp(cmd, &output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
- if (res != android::OK) {
- LOG(WARNING) << "blkid failed to identify " << path;
- return res;
- }
-
- for (const auto& line : output) {
- // Extract values from blkid output, if defined
- FindValue(line, "TYPE", fsType);
- FindValue(line, "UUID", fsUuid);
- FindValue(line, "LABEL", fsLabel);
- }
-
- return android::OK;
-}
-
-android::status_t ReadMetadata(const std::string& path, std::string* fsType, std::string* fsUuid,
- std::string* fsLabel) {
- return readMetadata(path, fsType, fsUuid, fsLabel, false);
-}
-
-android::status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType, std::string* fsUuid,
- std::string* fsLabel) {
- return readMetadata(path, fsType, fsUuid, fsLabel, true);
-}
-
-static std::vector<const char*> ConvertToArgv(const std::vector<std::string>& args) {
- std::vector<const char*> argv;
- argv.reserve(args.size() + 1);
- for (const auto& arg : args) {
- if (argv.empty()) {
- LOG(DEBUG) << arg;
- } else {
- LOG(DEBUG) << " " << arg;
- }
- argv.emplace_back(arg.data());
- }
- argv.emplace_back(nullptr);
- return argv;
-}
-
-static android::status_t ReadLinesFromFdAndLog(std::vector<std::string>* output,
- android::base::unique_fd ufd) {
- std::unique_ptr<FILE, int (*)(FILE*)> fp(android::base::Fdopen(std::move(ufd), "r"), fclose);
- if (!fp) {
- PLOG(ERROR) << "fdopen in ReadLinesFromFdAndLog";
- return -errno;
- }
- if (output) output->clear();
- char line[1024];
- while (fgets(line, sizeof(line), fp.get()) != nullptr) {
- LOG(DEBUG) << line;
- if (output) output->emplace_back(line);
- }
- return android::OK;
-}
-
-android::status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>* output,
- security_context_t context) {
- auto argv = ConvertToArgv(args);
-
- android::base::unique_fd pipe_read, pipe_write;
- if (!android::base::Pipe(&pipe_read, &pipe_write)) {
- PLOG(ERROR) << "Pipe in ForkExecvp";
- return -errno;
- }
-
- pid_t pid = fork();
- if (pid == 0) {
- if (context) {
- if (setexeccon(context)) {
- LOG(ERROR) << "Failed to setexeccon in ForkExecvp";
- abort();
- }
- }
- pipe_read.reset();
- if (dup2(pipe_write.get(), STDOUT_FILENO) == -1) {
- PLOG(ERROR) << "dup2 in ForkExecvp";
- _exit(EXIT_FAILURE);
- }
- pipe_write.reset();
- execvp(argv[0], const_cast<char**>(argv.data()));
- PLOG(ERROR) << "exec in ForkExecvp";
- _exit(EXIT_FAILURE);
- }
- if (pid == -1) {
- PLOG(ERROR) << "fork in ForkExecvp";
- return -errno;
- }
-
- pipe_write.reset();
- auto st = ReadLinesFromFdAndLog(output, std::move(pipe_read));
- if (st != 0) return st;
-
- int status;
- if (waitpid(pid, &status, 0) == -1) {
- PLOG(ERROR) << "waitpid in ForkExecvp";
- return -errno;
- }
- if (!WIFEXITED(status)) {
- LOG(ERROR) << "Process did not exit normally, status: " << status;
- return -ECHILD;
- }
- if (WEXITSTATUS(status)) {
- LOG(ERROR) << "Process exited with code: " << WEXITSTATUS(status);
- return WEXITSTATUS(status);
- }
- return android::OK;
-}
-
-pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
- auto argv = ConvertToArgv(args);
-
- pid_t pid = fork();
- if (pid == 0) {
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
-
- execvp(argv[0], const_cast<char**>(argv.data()));
- PLOG(ERROR) << "exec in ForkExecvpAsync";
- _exit(EXIT_FAILURE);
- }
- if (pid == -1) {
- PLOG(ERROR) << "fork in ForkExecvpAsync";
- return -1;
- }
- return pid;
-}
-
-android::status_t ReadRandomBytes(size_t bytes, std::string& out) {
- out.resize(bytes);
- return ReadRandomBytes(bytes, &out[0]);
-}
-
-android::status_t ReadRandomBytes(size_t bytes, char* buf) {
- int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
- if (fd == -1) {
- return -errno;
- }
-
- ssize_t n;
- while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], bytes))) > 0) {
- bytes -= n;
- buf += n;
- }
- close(fd);
-
- if (bytes == 0) {
- return android::OK;
- } else {
- return -EIO;
- }
-}
-
-android::status_t GenerateRandomUuid(std::string& out) {
- android::status_t res = ReadRandomBytes(16, out);
- if (res == android::OK) {
- out[6] &= 0x0f; /* clear version */
- out[6] |= 0x40; /* set to version 4 */
- out[8] &= 0x3f; /* clear variant */
- out[8] |= 0x80; /* set to IETF variant */
- }
- return res;
-}
-
-android::status_t HexToStr(const std::string& hex, std::string& str) {
- str.clear();
- bool even = true;
- char cur = 0;
- for (size_t i = 0; i < hex.size(); i++) {
- int val = 0;
- switch (hex[i]) {
- // clang-format off
- case ' ': case '-': case ':': continue;
- case 'f': case 'F': val = 15; break;
- case 'e': case 'E': val = 14; break;
- case 'd': case 'D': val = 13; break;
- case 'c': case 'C': val = 12; break;
- case 'b': case 'B': val = 11; break;
- case 'a': case 'A': val = 10; break;
- case '9': val = 9; break;
- case '8': val = 8; break;
- case '7': val = 7; break;
- case '6': val = 6; break;
- case '5': val = 5; break;
- case '4': val = 4; break;
- case '3': val = 3; break;
- case '2': val = 2; break;
- case '1': val = 1; break;
- case '0': val = 0; break;
- default: return -EINVAL;
- // clang-format on
- }
-
- if (even) {
- cur = val << 4;
- } else {
- cur += val;
- str.push_back(cur);
- cur = 0;
- }
- even = !even;
- }
- return even ? android::OK : -EINVAL;
-}
-
-static const char* kLookup = "0123456789abcdef";
-
-android::status_t StrToHex(const std::string& str, std::string& hex) {
- hex.clear();
- for (size_t i = 0; i < str.size(); i++) {
- hex.push_back(kLookup[(str[i] & 0xF0) >> 4]);
- hex.push_back(kLookup[str[i] & 0x0F]);
- }
- return android::OK;
-}
-
-android::status_t StrToHex(const KeyBuffer& str, KeyBuffer& hex) {
- hex.clear();
- for (size_t i = 0; i < str.size(); i++) {
- hex.push_back(kLookup[(str.data()[i] & 0xF0) >> 4]);
- hex.push_back(kLookup[str.data()[i] & 0x0F]);
- }
- return android::OK;
-}
-
-android::status_t NormalizeHex(const std::string& in, std::string& out) {
- std::string tmp;
- if (HexToStr(in, tmp)) {
- return -EINVAL;
- }
- return StrToHex(tmp, out);
-}
-
-android::status_t GetBlockDevSize(int fd, uint64_t* size) {
- if (ioctl(fd, BLKGETSIZE64, size)) {
- return -errno;
- }
-
- return android::OK;
-}
-
-android::status_t GetBlockDevSize(const std::string& path, uint64_t* size) {
- int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
- android::status_t res = android::OK;
-
- if (fd < 0) {
- return -errno;
- }
-
- res = GetBlockDevSize(fd, size);
-
- close(fd);
-
- return res;
-}
-
-android::status_t GetBlockDev512Sectors(const std::string& path, uint64_t* nr_sec) {
- uint64_t size;
- android::status_t res = GetBlockDevSize(path, &size);
-
- if (res != android::OK) {
- return res;
- }
-
- *nr_sec = size / 512;
-
- return android::OK;
-}
-
-uint64_t GetFreeBytes(const std::string& path) {
- struct statvfs sb;
- if (statvfs(path.c_str(), &sb) == 0) {
- return (uint64_t)sb.f_bavail * sb.f_frsize;
- } else {
- return -1;
- }
-}
-
-// TODO: borrowed from frameworks/native/libs/diskusage/ which should
-// eventually be migrated into system/
-static int64_t stat_size(struct stat* s) {
- int64_t blksize = s->st_blksize;
- // count actual blocks used instead of nominal file size
- int64_t size = s->st_blocks * 512;
-
- if (blksize) {
- /* round up to filesystem block size */
- size = (size + blksize - 1) & (~(blksize - 1));
- }
-
- return size;
-}
-
-// TODO: borrowed from frameworks/native/libs/diskusage/ which should
-// eventually be migrated into system/
-int64_t calculate_dir_size(int dfd) {
- int64_t size = 0;
- struct stat s;
- DIR* d;
- struct dirent* de;
-
- d = fdopendir(dfd);
- if (d == NULL) {
- close(dfd);
- return 0;
- }
-
- while ((de = readdir(d))) {
- const char* name = de->d_name;
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- size += stat_size(&s);
- }
- if (de->d_type == DT_DIR) {
- int subfd;
-
- /* always skip "." and ".." */
- if (name[0] == '.') {
- if (name[1] == 0) continue;
- if ((name[1] == '.') && (name[2] == 0)) continue;
- }
-
- subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
- if (subfd >= 0) {
- size += calculate_dir_size(subfd);
- }
- }
- }
- closedir(d);
- return size;
-}
-
-uint64_t GetTreeBytes(const std::string& path) {
- int dirfd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC);
- if (dirfd < 0) {
- PLOG(WARNING) << "Failed to open " << path;
- return -1;
- } else {
- return calculate_dir_size(dirfd);
- }
-}
-
-// TODO: Use a better way to determine if it's media provider app.
-bool IsFuseDaemon(const pid_t pid) {
- auto path = StringPrintf("/proc/%d/mounts", pid);
- char* tmp;
- if (lgetfilecon(path.c_str(), &tmp) < 0) {
- return false;
- }
- bool result = android::base::StartsWith(tmp, kMediaProviderAppCtx)
- || android::base::StartsWith(tmp, kMediaProviderCtx);
- freecon(tmp);
- return result;
-}
-
-bool IsFilesystemSupported(const std::string& fsType) {
- std::string supported;
- if (!ReadFileToString(kProcFilesystems, &supported)) {
- PLOG(ERROR) << "Failed to read supported filesystems";
- return false;
- }
- return supported.find(fsType + "\n") != std::string::npos;
-}
-
-bool IsSdcardfsUsed() {
- return IsFilesystemSupported("sdcardfs") &&
- android::base::GetBoolProperty(kExternalStorageSdcardfs, true);
-}
-
-android::status_t WipeBlockDevice(const std::string& path) {
- android::status_t res = -1;
- const char* c_path = path.c_str();
- uint64_t range[2] = {0, 0};
-
- int fd = TEMP_FAILURE_RETRY(open(c_path, O_RDWR | O_CLOEXEC));
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open " << path;
- goto done;
- }
-
- if (GetBlockDevSize(fd, &range[1]) != android::OK) {
- PLOG(ERROR) << "Failed to determine size of " << path;
- goto done;
- }
-
- LOG(INFO) << "About to discard " << range[1] << " on " << path;
- if (ioctl(fd, BLKDISCARD, &range) == 0) {
- LOG(INFO) << "Discard success on " << path;
- res = 0;
- } else {
- PLOG(ERROR) << "Discard failure on " << path;
- }
-
-done:
- close(fd);
- return res;
-}
-
-static bool isValidFilename(const std::string& name) {
- if (name.empty() || (name == ".") || (name == "..") || (name.find('/') != std::string::npos)) {
- return false;
- } else {
- return true;
- }
-}
-
-std::string BuildKeyPath(const std::string& partGuid) {
- return StringPrintf("%s/expand_%s.key", kKeyPath, partGuid.c_str());
-}
-
-std::string BuildDataSystemLegacyPath(userid_t userId) {
- return StringPrintf("%s/system/users/%u", BuildDataPath("").c_str(), userId);
-}
-
-std::string BuildDataSystemCePath(userid_t userId) {
- return StringPrintf("%s/system_ce/%u", BuildDataPath("").c_str(), userId);
-}
-
-std::string BuildDataSystemDePath(userid_t userId) {
- return StringPrintf("%s/system_de/%u", BuildDataPath("").c_str(), userId);
-}
-
-std::string BuildDataMiscLegacyPath(userid_t userId) {
- return StringPrintf("%s/misc/user/%u", BuildDataPath("").c_str(), userId);
-}
-
-std::string BuildDataMiscCePath(userid_t userId) {
- return StringPrintf("%s/misc_ce/%u", BuildDataPath("").c_str(), userId);
-}
-
-std::string BuildDataMiscDePath(userid_t userId) {
- return StringPrintf("%s/misc_de/%u", BuildDataPath("").c_str(), userId);
-}
-
-// Keep in sync with installd (frameworks/native/cmds/installd/utils.h)
-std::string BuildDataProfilesDePath(userid_t userId) {
- return StringPrintf("%s/misc/profiles/cur/%u", BuildDataPath("").c_str(), userId);
-}
-
-std::string BuildDataVendorCePath(userid_t userId) {
- return StringPrintf("%s/vendor_ce/%u", BuildDataPath("").c_str(), userId);
-}
-
-std::string BuildDataVendorDePath(userid_t userId) {
- return StringPrintf("%s/vendor_de/%u", BuildDataPath("").c_str(), userId);
-}
-
-std::string BuildDataPath(const std::string& volumeUuid) {
- // TODO: unify with installd path generation logic
- if (volumeUuid.empty()) {
- return "/data";
- } else {
- CHECK(isValidFilename(volumeUuid));
- return StringPrintf("/mnt/expand/%s", volumeUuid.c_str());
- }
-}
-
-std::string BuildDataMediaCePath(const std::string& volumeUuid, userid_t userId) {
- // TODO: unify with installd path generation logic
- std::string data(BuildDataPath(volumeUuid));
- return StringPrintf("%s/media/%u", data.c_str(), userId);
-}
-
-std::string BuildDataUserCePath(const std::string& volumeUuid, userid_t userId) {
- // TODO: unify with installd path generation logic
- std::string data(BuildDataPath(volumeUuid));
- if (volumeUuid.empty() && userId == 0) {
- std::string legacy = StringPrintf("%s/data", data.c_str());
- struct stat sb;
- if (lstat(legacy.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
- /* /data/data is dir, return /data/data for legacy system */
- return legacy;
- }
- }
- return StringPrintf("%s/user/%u", data.c_str(), userId);
-}
-
-std::string BuildDataUserDePath(const std::string& volumeUuid, userid_t userId) {
- // TODO: unify with installd path generation logic
- std::string data(BuildDataPath(volumeUuid));
- return StringPrintf("%s/user_de/%u", data.c_str(), userId);
-}
-
-dev_t GetDevice(const std::string& path) {
- struct stat sb;
- if (stat(path.c_str(), &sb)) {
- PLOG(WARNING) << "Failed to stat " << path;
- return 0;
- } else {
- return sb.st_dev;
- }
-}
-
-android::status_t RestoreconRecursive(const std::string& path) {
- LOG(DEBUG) << "Starting restorecon of " << path;
-
- static constexpr const char* kRestoreconString = "selinux.restorecon_recursive";
-
- android::base::SetProperty(kRestoreconString, "");
- android::base::SetProperty(kRestoreconString, path);
-
- android::base::WaitForProperty(kRestoreconString, path);
-
- LOG(DEBUG) << "Finished restorecon of " << path;
- return android::OK;
-}
-
-bool Readlinkat(int dirfd, const std::string& path, std::string* result) {
- // Shamelessly borrowed from android::base::Readlink()
- result->clear();
-
- // Most Linux file systems (ext2 and ext4, say) limit symbolic links to
- // 4095 bytes. Since we'll copy out into the string anyway, it doesn't
- // waste memory to just start there. We add 1 so that we can recognize
- // whether it actually fit (rather than being truncated to 4095).
- std::vector<char> buf(4095 + 1);
- while (true) {
- ssize_t size = readlinkat(dirfd, path.c_str(), &buf[0], buf.size());
- // Unrecoverable error?
- if (size == -1) return false;
- // It fit! (If size == buf.size(), it may have been truncated.)
- if (static_cast<size_t>(size) < buf.size()) {
- result->assign(&buf[0], size);
- return true;
- }
- // Double our buffer and try again.
- buf.resize(buf.size() * 2);
- }
-}
-
-static unsigned int GetMajorBlockVirtioBlk() {
- std::string devices;
- if (!ReadFileToString(kProcDevices, &devices)) {
- PLOG(ERROR) << "Unable to open /proc/devices";
- return 0;
- }
-
- bool blockSection = false;
- for (auto line : android::base::Split(devices, "\n")) {
- if (line == "Block devices:") {
- blockSection = true;
- } else if (line == "Character devices:") {
- blockSection = false;
- } else if (blockSection) {
- auto tokens = android::base::Split(line, " ");
- if (tokens.size() == 2 && tokens[1] == "virtblk") {
- return std::stoul(tokens[0]);
- }
- }
- }
-
- return 0;
-}
-
-bool IsVirtioBlkDevice(unsigned int major) {
- // Most virtualized platforms expose block devices with the virtio-blk
- // block device driver. Unfortunately, this driver does not use a fixed
- // major number, but relies on the kernel to assign one from a specific
- // range of block majors, which are allocated for "LOCAL/EXPERIMENAL USE"
- // per Documentation/devices.txt. This is true even for the latest Linux
- // kernel (4.4; see init() in drivers/block/virtio_blk.c).
- static unsigned int kMajorBlockVirtioBlk = GetMajorBlockVirtioBlk();
- return kMajorBlockVirtioBlk && major == kMajorBlockVirtioBlk;
-}
-
-static android::status_t findMountPointsWithPrefix(const std::string& prefix,
- std::list<std::string>& mountPoints) {
- // Add a trailing slash if the client didn't provide one so that we don't match /foo/barbaz
- // when the prefix is /foo/bar
- std::string prefixWithSlash(prefix);
- if (prefix.back() != '/') {
- android::base::StringAppendF(&prefixWithSlash, "/");
- }
-
- std::unique_ptr<FILE, int (*)(FILE*)> mnts(setmntent("/proc/mounts", "re"), endmntent);
- if (!mnts) {
- PLOG(ERROR) << "Unable to open /proc/mounts";
- return -errno;
- }
-
- // Some volumes can be stacked on each other, so force unmount in
- // reverse order to give us the best chance of success.
- struct mntent* mnt; // getmntent returns a thread local, so it's safe.
- while ((mnt = getmntent(mnts.get())) != nullptr) {
- auto mountPoint = std::string(mnt->mnt_dir) + "/";
- if (android::base::StartsWith(mountPoint, prefixWithSlash)) {
- mountPoints.push_front(mountPoint);
- }
- }
- return android::OK;
-}
-
-// Unmount all mountpoints that start with prefix. prefix itself doesn't need to be a mountpoint.
-android::status_t UnmountTreeWithPrefix(const std::string& prefix) {
- std::list<std::string> toUnmount;
- android::status_t result = findMountPointsWithPrefix(prefix, toUnmount);
- if (result < 0) {
- return result;
- }
- for (const auto& path : toUnmount) {
- if (umount2(path.c_str(), MNT_DETACH)) {
- PLOG(ERROR) << "Failed to unmount " << path;
- result = -errno;
- }
- }
- return result;
-}
-
-android::status_t UnmountTree(const std::string& mountPoint) {
- if (TEMP_FAILURE_RETRY(umount2(mountPoint.c_str(), MNT_DETACH)) < 0 && errno != EINVAL &&
- errno != ENOENT) {
- PLOG(ERROR) << "Failed to unmount " << mountPoint;
- return -errno;
- }
- return android::OK;
-}
-
-static android::status_t delete_dir_contents(DIR* dir) {
- // Shamelessly borrowed from android::installd
- int dfd = dirfd(dir);
- if (dfd < 0) {
- return -errno;
- }
-
- android::status_t result = android::OK;
- struct dirent* de;
- while ((de = readdir(dir))) {
- const char* name = de->d_name;
- if (de->d_type == DT_DIR) {
- /* always skip "." and ".." */
- if (name[0] == '.') {
- if (name[1] == 0) continue;
- if ((name[1] == '.') && (name[2] == 0)) continue;
- }
-
- android::base::unique_fd subfd(
- openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC));
- if (subfd.get() == -1) {
- PLOG(ERROR) << "Couldn't openat " << name;
- result = -errno;
- continue;
- }
- std::unique_ptr<DIR, decltype(&closedir)> subdirp(
- android::base::Fdopendir(std::move(subfd)), closedir);
- if (!subdirp) {
- PLOG(ERROR) << "Couldn't fdopendir " << name;
- result = -errno;
- continue;
- }
- result = delete_dir_contents(subdirp.get());
- if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
- PLOG(ERROR) << "Couldn't unlinkat " << name;
- result = -errno;
- }
- } else {
- if (unlinkat(dfd, name, 0) < 0) {
- PLOG(ERROR) << "Couldn't unlinkat " << name;
- result = -errno;
- }
- }
- }
- return result;
-}
-
-android::status_t DeleteDirContentsAndDir(const std::string& pathname) {
- android::status_t res = DeleteDirContents(pathname);
- if (res < 0) {
- return res;
- }
- if (TEMP_FAILURE_RETRY(rmdir(pathname.c_str())) < 0 && errno != ENOENT) {
- PLOG(ERROR) << "rmdir failed on " << pathname;
- return -errno;
- }
- LOG(VERBOSE) << "Success: rmdir on " << pathname;
- return android::OK;
-}
-
-android::status_t DeleteDirContents(const std::string& pathname) {
- // Shamelessly borrowed from android::installd
- std::unique_ptr<DIR, decltype(&closedir)> dirp(opendir(pathname.c_str()), closedir);
- if (!dirp) {
- if (errno == ENOENT) {
- return android::OK;
- }
- PLOG(ERROR) << "Failed to opendir " << pathname;
- return -errno;
- }
- return delete_dir_contents(dirp.get());
-}
-
-// TODO(118708649): fix duplication with init/util.h
-android::status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout) {
- android::base::Timer t;
- while (t.duration() < timeout) {
- struct stat sb;
- if (stat(filename, &sb) != -1) {
- LOG(INFO) << "wait for '" << filename << "' took " << t;
- return 0;
- }
- std::this_thread::sleep_for(10ms);
- }
- LOG(WARNING) << "wait for '" << filename << "' timed out and took " << t;
- return -1;
-}
-
-bool FsyncDirectory(const std::string& dirname) {
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dirname.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open " << dirname;
- return false;
- }
- if (fsync(fd) == -1) {
- if (errno == EROFS || errno == EINVAL) {
- PLOG(WARNING) << "Skip fsync " << dirname
- << " on a file system does not support synchronization";
- } else {
- PLOG(ERROR) << "Failed to fsync " << dirname;
- return false;
- }
- }
- return true;
-}
-
-bool writeStringToFile(const std::string& payload, const std::string& filename) {
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(
- open(filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0666)));
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open " << filename;
- return false;
- }
- if (!android::base::WriteStringToFd(payload, fd)) {
- PLOG(ERROR) << "Failed to write to " << filename;
- unlink(filename.c_str());
- return false;
- }
- // fsync as close won't guarantee flush data
- // see close(2), fsync(2) and b/68901441
- if (fsync(fd) == -1) {
- if (errno == EROFS || errno == EINVAL) {
- PLOG(WARNING) << "Skip fsync " << filename
- << " on a file system does not support synchronization";
- } else {
- PLOG(ERROR) << "Failed to fsync " << filename;
- unlink(filename.c_str());
- return false;
- }
- }
- return true;
-}
-
-android::status_t AbortFuseConnections() {
- namespace fs = std::filesystem;
-
- for (const auto& itEntry : fs::directory_iterator("/sys/fs/fuse/connections")) {
- std::string abortPath = itEntry.path().string() + "/abort";
- LOG(DEBUG) << "Aborting fuse connection entry " << abortPath;
- bool ret = writeStringToFile("1", abortPath);
- if (!ret) {
- LOG(WARNING) << "Failed to write to " << abortPath;
- }
- }
-
- return android::OK;
-}
-
-android::status_t EnsureDirExists(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
- if (access(path.c_str(), F_OK) != 0) {
- PLOG(WARNING) << "Dir does not exist: " << path;
- if (fs_prepare_dir(path.c_str(), mode, uid, gid) != 0) {
- return -errno;
- }
- }
- return android::OK;
-}
-
-// Gets the sysfs path for parameters of the backing device info (bdi)
-static std::string getBdiPathForMount(const std::string& mount) {
- // First figure out MAJOR:MINOR of mount. Simplest way is to stat the path.
- struct stat info;
- if (stat(mount.c_str(), &info) != 0) {
- PLOG(ERROR) << "Failed to stat " << mount;
- return "";
- }
- unsigned int maj = major(info.st_dev);
- unsigned int min = minor(info.st_dev);
-
- return StringPrintf("/sys/class/bdi/%u:%u", maj, min);
-}
-
-// Configures max_ratio for the FUSE filesystem.
-void ConfigureMaxDirtyRatioForFuse(const std::string& fuse_mount, unsigned int max_ratio) {
- LOG(INFO) << "Configuring max_ratio of " << fuse_mount << " fuse filesystem to " << max_ratio;
- if (max_ratio > 100) {
- LOG(ERROR) << "Invalid max_ratio: " << max_ratio;
- return;
- }
- std::string fuseBdiPath = getBdiPathForMount(fuse_mount);
- if (fuseBdiPath == "") {
- return;
- }
- std::string max_ratio_file = StringPrintf("%s/max_ratio", fuseBdiPath.c_str());
- unique_fd fd(TEMP_FAILURE_RETRY(open(max_ratio_file.c_str(), O_WRONLY | O_CLOEXEC)));
- if (fd.get() == -1) {
- PLOG(ERROR) << "Failed to open " << max_ratio_file;
- return;
- }
- LOG(INFO) << "Writing " << max_ratio << " to " << max_ratio_file;
- if (!WriteStringToFd(std::to_string(max_ratio), fd)) {
- PLOG(ERROR) << "Failed to write to " << max_ratio_file;
- }
-}
-
-// Configures read ahead property of the fuse filesystem with the mount point |fuse_mount| by
-// writing |read_ahead_kb| to the /sys/class/bdi/MAJOR:MINOR/read_ahead_kb.
-void ConfigureReadAheadForFuse(const std::string& fuse_mount, size_t read_ahead_kb) {
- LOG(INFO) << "Configuring read_ahead of " << fuse_mount << " fuse filesystem to "
- << read_ahead_kb << "kb";
- std::string fuseBdiPath = getBdiPathForMount(fuse_mount);
- if (fuseBdiPath == "") {
- return;
- }
- // We found the bdi path for our filesystem, time to configure read ahead!
- std::string read_ahead_file = StringPrintf("%s/read_ahead_kb", fuseBdiPath.c_str());
- unique_fd fd(TEMP_FAILURE_RETRY(open(read_ahead_file.c_str(), O_WRONLY | O_CLOEXEC)));
- if (fd.get() == -1) {
- PLOG(ERROR) << "Failed to open " << read_ahead_file;
- return;
- }
- LOG(INFO) << "Writing " << read_ahead_kb << " to " << read_ahead_file;
- if (!WriteStringToFd(std::to_string(read_ahead_kb), fd)) {
- PLOG(ERROR) << "Failed to write to " << read_ahead_file;
- }
-}
-
-android::status_t MountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
- const std::string& relative_upper_path, android::base::unique_fd* fuse_fd) {
- std::string pre_fuse_path(StringPrintf("/mnt/user/%d", user_id));
- std::string fuse_path(
- StringPrintf("%s/%s", pre_fuse_path.c_str(), relative_upper_path.c_str()));
-
- std::string pre_pass_through_path(StringPrintf("/mnt/pass_through/%d", user_id));
- std::string pass_through_path(
- StringPrintf("%s/%s", pre_pass_through_path.c_str(), relative_upper_path.c_str()));
-
- // Ensure that /mnt/user is 0700. With FUSE, apps don't need access to /mnt/user paths directly.
- // Without FUSE however, apps need /mnt/user access so /mnt/user in init.rc is 0755 until here
- auto result = PrepareDir("/mnt/user", 0750, AID_ROOT, AID_MEDIA_RW);
- if (result != android::OK) {
- PLOG(ERROR) << "Failed to prepare directory /mnt/user";
- return -1;
- }
-
- // Shell is neither AID_ROOT nor AID_EVERYBODY. Since it equally needs 'execute' access to
- // /mnt/user/0 to 'adb shell ls /sdcard' for instance, we set the uid bit of /mnt/user/0 to
- // AID_SHELL. This gives shell access along with apps running as group everybody (user 0 apps)
- // These bits should be consistent with what is set in zygote in
- // com_android_internal_os_Zygote#MountEmulatedStorage on volume bind mount during app fork
- result = PrepareDir(pre_fuse_path, 0710, user_id ? AID_ROOT : AID_SHELL,
- multiuser_get_uid(user_id, AID_EVERYBODY));
- if (result != android::OK) {
- PLOG(ERROR) << "Failed to prepare directory " << pre_fuse_path;
- return -1;
- }
-
- result = PrepareDir(fuse_path, 0700, AID_ROOT, AID_ROOT);
- if (result != android::OK) {
- PLOG(ERROR) << "Failed to prepare directory " << fuse_path;
- return -1;
- }
-
- result = PrepareDir(pre_pass_through_path, 0710, AID_ROOT, AID_MEDIA_RW);
- if (result != android::OK) {
- PLOG(ERROR) << "Failed to prepare directory " << pre_pass_through_path;
- return -1;
- }
-
- result = PrepareDir(pass_through_path, 0710, AID_ROOT, AID_MEDIA_RW);
- if (result != android::OK) {
- PLOG(ERROR) << "Failed to prepare directory " << pass_through_path;
- return -1;
- }
-
- if (relative_upper_path == "emulated") {
- std::string linkpath(StringPrintf("/mnt/user/%d/self", user_id));
- result = PrepareDir(linkpath, 0755, AID_ROOT, AID_ROOT);
- if (result != android::OK) {
- PLOG(ERROR) << "Failed to prepare directory " << linkpath;
- return -1;
- }
- linkpath += "/primary";
- Symlink("/storage/emulated/" + std::to_string(user_id), linkpath);
-
- std::string pass_through_linkpath(StringPrintf("/mnt/pass_through/%d/self", user_id));
- result = PrepareDir(pass_through_linkpath, 0710, AID_ROOT, AID_MEDIA_RW);
- if (result != android::OK) {
- PLOG(ERROR) << "Failed to prepare directory " << pass_through_linkpath;
- return -1;
- }
- pass_through_linkpath += "/primary";
- Symlink("/storage/emulated/" + std::to_string(user_id), pass_through_linkpath);
- }
-
- // Open fuse fd.
- fuse_fd->reset(open("/dev/fuse", O_RDWR | O_CLOEXEC));
- if (fuse_fd->get() == -1) {
- PLOG(ERROR) << "Failed to open /dev/fuse";
- return -1;
- }
-
- // Note: leaving out default_permissions since we don't want kernel to do lower filesystem
- // permission checks before routing to FUSE daemon.
- const auto opts = StringPrintf(
- "fd=%i,"
- "rootmode=40000,"
- "allow_other,"
- "user_id=0,group_id=0,",
- fuse_fd->get());
-
- result = TEMP_FAILURE_RETRY(mount("/dev/fuse", fuse_path.c_str(), "fuse",
- MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME | MS_LAZYTIME,
- opts.c_str()));
- if (result != 0) {
- PLOG(ERROR) << "Failed to mount " << fuse_path;
- return -errno;
- }
-
- if (IsSdcardfsUsed()) {
- std::string sdcardfs_path(
- StringPrintf("/mnt/runtime/full/%s", relative_upper_path.c_str()));
-
- LOG(INFO) << "Bind mounting " << sdcardfs_path << " to " << pass_through_path;
- return BindMount(sdcardfs_path, pass_through_path);
- } else {
- LOG(INFO) << "Bind mounting " << absolute_lower_path << " to " << pass_through_path;
- return BindMount(absolute_lower_path, pass_through_path);
- }
-}
-
-android::status_t UnmountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
- const std::string& relative_upper_path) {
- std::string fuse_path(StringPrintf("/mnt/user/%d/%s", user_id, relative_upper_path.c_str()));
- std::string pass_through_path(
- StringPrintf("/mnt/pass_through/%d/%s", user_id, relative_upper_path.c_str()));
-
- // Best effort unmount pass_through path
- sSleepOnUnmount = false;
- LOG(INFO) << "Unmounting pass_through_path " << pass_through_path;
- auto status = ForceUnmount(pass_through_path);
- if (status != android::OK) {
- LOG(ERROR) << "Failed to unmount " << pass_through_path;
- }
- rmdir(pass_through_path.c_str());
-
- LOG(INFO) << "Unmounting fuse path " << fuse_path;
- android::status_t result = ForceUnmount(fuse_path);
- sSleepOnUnmount = true;
- if (result != android::OK) {
- // TODO(b/135341433): MNT_DETACH is needed for fuse because umount2 can fail with EBUSY.
- // Figure out why we get EBUSY and remove this special casing if possible.
- PLOG(ERROR) << "Failed to unmount. Trying MNT_DETACH " << fuse_path << " ...";
- if (umount2(fuse_path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) && errno != EINVAL &&
- errno != ENOENT) {
- PLOG(ERROR) << "Failed to unmount with MNT_DETACH " << fuse_path;
- return -errno;
- }
- result = android::OK;
- }
- rmdir(fuse_path.c_str());
-
- return result;
-}
-
-android::status_t PrepareAndroidDirs(const std::string& volumeRoot) {
- std::string androidDir = volumeRoot + kAndroidDir;
- std::string androidDataDir = volumeRoot + kAppDataDir;
- std::string androidObbDir = volumeRoot + kAppObbDir;
- std::string androidMediaDir = volumeRoot + kAppMediaDir;
-
- bool useSdcardFs = IsSdcardfsUsed();
-
- // mode 0771 + sticky bit for inheriting GIDs
- mode_t mode = S_IRWXU | S_IRWXG | S_IXOTH | S_ISGID;
- if (fs_prepare_dir(androidDir.c_str(), mode, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
- PLOG(ERROR) << "Failed to create " << androidDir;
- return -errno;
- }
-
- gid_t dataGid = useSdcardFs ? AID_MEDIA_RW : AID_EXT_DATA_RW;
- if (fs_prepare_dir(androidDataDir.c_str(), mode, AID_MEDIA_RW, dataGid) != 0) {
- PLOG(ERROR) << "Failed to create " << androidDataDir;
- return -errno;
- }
-
- gid_t obbGid = useSdcardFs ? AID_MEDIA_RW : AID_EXT_OBB_RW;
- if (fs_prepare_dir(androidObbDir.c_str(), mode, AID_MEDIA_RW, obbGid) != 0) {
- PLOG(ERROR) << "Failed to create " << androidObbDir;
- return -errno;
- }
- // Some other apps, like installers, have write access to the OBB directory
- // to pre-download them. To make sure newly created folders in this directory
- // have the right permissions, set a default ACL.
- SetDefaultAcl(androidObbDir, mode, AID_MEDIA_RW, obbGid, {});
-
- if (fs_prepare_dir(androidMediaDir.c_str(), mode, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
- PLOG(ERROR) << "Failed to create " << androidMediaDir;
- return -errno;
- }
-
- return android::OK;
-}
diff --git a/crypto/fscrypt/Utils.h b/crypto/fscrypt/Utils.h
deleted file mode 100755
index e820711..0000000
--- a/crypto/fscrypt/Utils.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2015 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 ANDROID_VOLD_UTILS_H
-#define ANDROID_VOLD_UTILS_H
-
-#include "KeyBuffer.h"
-
-#include <android-base/macros.h>
-#include <android-base/unique_fd.h>
-#include <cutils/multiuser.h>
-#include <selinux/selinux.h>
-#include <utils/Errors.h>
-
-#include <chrono>
-#include <string>
-#include <vector>
-
-struct DIR;
-
-static const char* kPropFuse = "persist.sys.fuse";
-static const char* kVoldAppDataIsolationEnabled = "persist.sys.vold_app_data_isolation_enabled";
-static const char* kExternalStorageSdcardfs = "external_storage.sdcardfs.enabled";
-
-/* SELinux contexts used depending on the block device type */
-extern security_context_t sBlkidContext;
-extern security_context_t sBlkidUntrustedContext;
-extern security_context_t sFsckContext;
-extern security_context_t sFsckUntrustedContext;
-
-// TODO remove this with better solution, b/64143519
-extern bool sSleepOnUnmount;
-
-std::string GetFuseMountPathForUser(userid_t user_id, const std::string& relative_upper_path);
-
-android::status_t CreateDeviceNode(const std::string& path, dev_t dev);
-android::status_t DestroyDeviceNode(const std::string& path);
-
-android::status_t AbortFuseConnections();
-
-int SetQuotaInherit(const std::string& path);
-int SetQuotaProjectId(const std::string& path, long projectId);
-/*
- * Creates and sets up an application-specific path on external
- * storage with the correct ACL and project ID (if needed).
- *
- * ONLY for use with app-specific data directories on external storage!
- * (eg, /Android/data/com.foo, /Android/obb/com.foo, etc.)
- */
-int PrepareAppDirFromRoot(const std::string& path, const std::string& root, int appUid,
- bool fixupExisting);
-
-/* fs_prepare_dir wrapper that creates with SELinux context */
-android::status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid);
-
-/* Really unmounts the path, killing active processes along the way */
-android::status_t ForceUnmount(const std::string& path);
-
-/* Kills any processes using given path */
-android::status_t KillProcessesUsingPath(const std::string& path);
-
-/* Kills any processes using given mount prifix */
-android::status_t KillProcessesWithMountPrefix(const std::string& path);
-
-/* Creates bind mount from source to target */
-android::status_t BindMount(const std::string& source, const std::string& target);
-
-/** Creates a symbolic link to target */
-android::status_t Symlink(const std::string& target, const std::string& linkpath);
-
-/** Calls unlink(2) at linkpath */
-android::status_t Unlink(const std::string& linkpath);
-
-/** Creates the given directory if it is not already available */
-android::status_t CreateDir(const std::string& dir, mode_t mode);
-
-bool FindValue(const std::string& raw, const std::string& key, std::string* value);
-
-/* Reads filesystem metadata from device at path */
-android::status_t ReadMetadata(const std::string& path, std::string* fsType, std::string* fsUuid,
- std::string* fsLabel);
-
-/* Reads filesystem metadata from untrusted device at path */
-android::status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType, std::string* fsUuid,
- std::string* fsLabel);
-
-/* Returns either WEXITSTATUS() status, or a negative errno */
-android::status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>* output = nullptr,
- security_context_t context = nullptr);
-
-pid_t ForkExecvpAsync(const std::vector<std::string>& args);
-
-/* Gets block device size in bytes */
-android::status_t GetBlockDevSize(int fd, uint64_t* size);
-android::status_t GetBlockDevSize(const std::string& path, uint64_t* size);
-/* Gets block device size in 512 byte sectors */
-android::status_t GetBlockDev512Sectors(const std::string& path, uint64_t* nr_sec);
-
-android::status_t ReadRandomBytes(size_t bytes, std::string& out);
-android::status_t ReadRandomBytes(size_t bytes, char* buffer);
-android::status_t GenerateRandomUuid(std::string& out);
-
-/* Converts hex string to raw bytes, ignoring [ :-] */
-android::status_t HexToStr(const std::string& hex, std::string& str);
-/* Converts raw bytes to hex string */
-android::status_t StrToHex(const std::string& str, std::string& hex);
-/* Converts raw key bytes to hex string */
-android::status_t StrToHex(const KeyBuffer& str, KeyBuffer& hex);
-/* Normalize given hex string into consistent format */
-android::status_t NormalizeHex(const std::string& in, std::string& out);
-
-uint64_t GetFreeBytes(const std::string& path);
-uint64_t GetTreeBytes(const std::string& path);
-
-bool IsFilesystemSupported(const std::string& fsType);
-bool IsSdcardfsUsed();
-bool IsFuseDaemon(const pid_t pid);
-
-/* Wipes contents of block device at given path */
-android::status_t WipeBlockDevice(const std::string& path);
-
-std::string BuildKeyPath(const std::string& partGuid);
-
-std::string BuildDataSystemLegacyPath(userid_t userid);
-std::string BuildDataSystemCePath(userid_t userid);
-std::string BuildDataSystemDePath(userid_t userid);
-std::string BuildDataMiscLegacyPath(userid_t userid);
-std::string BuildDataMiscCePath(userid_t userid);
-std::string BuildDataMiscDePath(userid_t userid);
-std::string BuildDataProfilesDePath(userid_t userid);
-std::string BuildDataVendorCePath(userid_t userid);
-std::string BuildDataVendorDePath(userid_t userid);
-
-std::string BuildDataPath(const std::string& volumeUuid);
-std::string BuildDataMediaCePath(const std::string& volumeUuid, userid_t userid);
-std::string BuildDataUserCePath(const std::string& volumeUuid, userid_t userid);
-std::string BuildDataUserDePath(const std::string& volumeUuid, userid_t userid);
-
-dev_t GetDevice(const std::string& path);
-
-android::status_t EnsureDirExists(const std::string& path, mode_t mode, uid_t uid, gid_t gid);
-
-android::status_t RestoreconRecursive(const std::string& path);
-
-// TODO: promote to android::base
-bool Readlinkat(int dirfd, const std::string& path, std::string* result);
-
-// Handles dynamic major assignment for virtio-block
-bool IsVirtioBlkDevice(unsigned int major);
-
-android::status_t UnmountTreeWithPrefix(const std::string& prefix);
-android::status_t UnmountTree(const std::string& mountPoint);
-
-android::status_t DeleteDirContentsAndDir(const std::string& pathname);
-android::status_t DeleteDirContents(const std::string& pathname);
-
-android::status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout);
-
-bool FsyncDirectory(const std::string& dirname);
-
-bool writeStringToFile(const std::string& payload, const std::string& filename);
-
-void ConfigureMaxDirtyRatioForFuse(const std::string& fuse_mount, unsigned int max_ratio);
-
-void ConfigureReadAheadForFuse(const std::string& fuse_mount, size_t read_ahead_kb);
-
-android::status_t MountUserFuse(userid_t user_id, const std::string& absolute_lower_path,
- const std::string& relative_upper_path, android::base::unique_fd* fuse_fd);
-
-android::status_t UnmountUserFuse(userid_t userId, const std::string& absolute_lower_path,
- const std::string& relative_upper_path);
-
-android::status_t PrepareAndroidDirs(const std::string& volumeRoot);
-
-#endif
diff --git a/crypto/fscrypt/VoldUtil.cpp b/crypto/fscrypt/VoldUtil.cpp
deleted file mode 100644
index 082f743..0000000
--- a/crypto/fscrypt/VoldUtil.cpp
+++ /dev/null
@@ -1,19 +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 "VoldUtil.h"
-
-android::fs_mgr::Fstab fstab_default;
diff --git a/crypto/fscrypt/VoldUtil.h b/crypto/fscrypt/VoldUtil.h
deleted file mode 100644
index e0945bf..0000000
--- a/crypto/fscrypt/VoldUtil.h
+++ /dev/null
@@ -1,24 +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.
- */
-
-#pragma once
-
-#include <fstab/fstab.h>
-
-extern android::fs_mgr::Fstab fstab_default;
-
-#define DATA_MNT_POINT "/data"
-#define METADATA_MNT_POINT "/metadata"
diff --git a/crypto/fscrypt/Weaver1.cpp b/crypto/fscrypt/Weaver1.cpp
deleted file mode 100644
index ea357ed..0000000
--- a/crypto/fscrypt/Weaver1.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2017 Team Win Recovery 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 the best of my knowledge there is no native implementation for
- * Weaver so I made this by looking at the IWeaver.h file that gets
- * compiled by the build system. I took the information from this header
- * file and looked at keymaster source to get an idea of the proper way
- * to write the functions.
- */
-
-#include "Weaver1.h"
-
-//#include <android-base/logging.h>
-//#include <keystore/keymaster_tags.h>
-//#include <keystore/authorization_set.h>
-//#include <keystore/keystore_hidl_support.h>
-
-#include <android/hardware/weaver/1.0/IWeaver.h>
-
-#include <iostream>
-#define ERROR 1
-#define LOG(x) std::cout
-
-using namespace android::hardware::weaver;
-using android::hardware::hidl_string;
-using ::android::hardware::weaver::V1_0::IWeaver;
-using ::android::hardware::weaver::V1_0::WeaverConfig;
-using ::android::hardware::weaver::V1_0::WeaverReadStatus;
-using ::android::hardware::weaver::V1_0::WeaverReadResponse;
-using ::android::hardware::weaver::V1_0::WeaverStatus;
-using ::android::hardware::Return;
-using ::android::sp;
-
-namespace android {
-namespace vold {
-
-Weaver::Weaver() {
- mDevice = ::android::hardware::weaver::V1_0::IWeaver::getService();
- GottenConfig = false;
-}
-
-bool Weaver::GetConfig() {
- if (GottenConfig)
- return true;
-
- WeaverStatus status;
- WeaverConfig cfg;
-
- bool callbackCalled = false;
- auto ret = mDevice->getConfig([&](WeaverStatus s, WeaverConfig c) {
- callbackCalled = true;
- status = s;
- cfg = c;
- });
- if (ret.isOk() && callbackCalled && status == WeaverStatus::OK) {
- config = cfg;
- GottenConfig = true;
- return true;
- }
- return false;
-}
-
-bool Weaver::GetSlots(uint32_t* slots) {
- if (!GetConfig())
- return false;
- *slots = config.slots;
- return true;
-}
-
-bool Weaver::GetKeySize(uint32_t* keySize) {
- if (!GetConfig())
- return false;
- *keySize = config.keySize;
- return true;
-}
-
-bool Weaver::GetValueSize(uint32_t* valueSize) {
- if (!GetConfig())
- return false;
- *valueSize = config.valueSize;
- return true;
-}
-
-// TODO: we should return more information about the status including time delays before the next retry
-bool Weaver::WeaverVerify(const uint32_t slot, const void* weaver_key, std::vector<uint8_t>* payload) {
- bool callbackCalled = false;
- WeaverReadStatus status;
- std::vector<uint8_t> readValue;
- uint32_t timeout;
- uint32_t keySize;
- if (!GetKeySize(&keySize))
- return false;
- std::vector<uint8_t> key;
- key.resize(keySize);
- uint32_t index = 0;
- unsigned char* ptr = (unsigned char*)weaver_key;
- for (index = 0; index < keySize; index++) {
- key[index] = *ptr;
- ptr++;
- }
- const auto readRet = mDevice->read(slot, key, [&](WeaverReadStatus s, WeaverReadResponse r) {
- callbackCalled = true;
- status = s;
- readValue = r.value;
- timeout = r.timeout;
- });
- if (readRet.isOk() && callbackCalled && status == WeaverReadStatus::OK && timeout == 0) {
- *payload = readValue;
- return true;
- }
- return false;
-}
-
-} // namespace vold
-} // namespace android
diff --git a/crypto/fscrypt/Weaver1.h b/crypto/fscrypt/Weaver1.h
deleted file mode 100644
index 22f401e..0000000
--- a/crypto/fscrypt/Weaver1.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2017 Team Win Recovery 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 the best of my knowledge there is no native implementation for
- * Weaver so I made this by looking at the IWeaver.h file that gets
- * compiled by the build system. I took the information from this header
- * file and looked at keymaster source to get an idea of the proper way
- * to write the functions.
- */
-
-#ifndef TWRP_WEAVER_H
-#define TWRP_WEAVER_H
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include <android/hardware/weaver/1.0/IWeaver.h>
-#include "Utils.h"
-
-namespace android {
-namespace vold {
-using ::android::hardware::weaver::V1_0::IWeaver;
-
-// Wrapper for a Weaver device
-class Weaver {
- public:
- Weaver();
- // false if we failed to open the weaver device.
- explicit operator bool() { return mDevice.get() != nullptr; }
-
- bool GetSlots(uint32_t* slots);
- bool GetKeySize(uint32_t* keySize);
- bool GetValueSize(uint32_t* valueSize);
- // TODO: we should return more information about the status including time delays before the next retry
- bool WeaverVerify(const uint32_t slot, const void* weaver_key, std::vector<uint8_t>* payload);
-
- private:
- sp<hardware::weaver::V1_0::IWeaver> mDevice;
- hardware::weaver::V1_0::WeaverConfig config;
- bool GottenConfig;
-
- bool GetConfig();
-
- DISALLOW_COPY_AND_ASSIGN(Weaver);
-};
-
-} // namespace vold
-} // namespace android
-
-#endif
diff --git a/crypto/fscrypt/cryptfs.cpp b/crypto/fscrypt/cryptfs.cpp
deleted file mode 100644
index b58c343..0000000
--- a/crypto/fscrypt/cryptfs.cpp
+++ /dev/null
@@ -1,2902 +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.
- */
-
-#define LOG_TAG "Cryptfs"
-
-#include "cryptfs.h"
-
-#include "Checkpoint.h"
-#include "CryptoType.h"
-#include "EncryptInplace.h"
-#include "FsCrypt.h"
-#include "Keymaster.h"
-#include "Process.h"
-#include "ScryptParameters.h"
-#include "Utils.h"
-#include "VoldUtil.h"
-#include "VolumeManager.h"
-
-#include <android-base/parseint.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <bootloader_message/bootloader_message.h>
-#include <cutils/android_reboot.h>
-#include <cutils/properties.h>
-#include <ext4_utils/ext4_utils.h>
-#include <f2fs_sparseblock.h>
-#include <fs_mgr.h>
-#include <fscrypt/fscrypt.h>
-#include <libdm/dm.h>
-#include <log/log.h>
-#include <logwrap/logwrap.h>
-#include <openssl/evp.h>
-#include <openssl/sha.h>
-#include <selinux/selinux.h>
-// #include <wakelock/wakelock.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <libgen.h>
-#include <linux/kdev_t.h>
-#include <math.h>
-#include <mntent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <chrono>
-#include <thread>
-
-extern "C" {
-#include <crypto_scrypt.h>
-}
-
-using android::base::ParseUint;
-using android::base::StringPrintf;
-using android::fs_mgr::GetEntryForMountPoint;
-using ::CryptoType;
-using ::KeyBuffer;
-using ::KeyGeneration;
-using namespace android::dm;
-using namespace std::chrono_literals;
-
-/* The current cryptfs version */
-#define CURRENT_MAJOR_VERSION 1
-#define CURRENT_MINOR_VERSION 3
-
-#define CRYPT_FOOTER_TO_PERSIST_OFFSET 0x1000
-#define CRYPT_PERSIST_DATA_SIZE 0x1000
-
-#define MAX_CRYPTO_TYPE_NAME_LEN 64
-
-#define MAX_KEY_LEN 48
-#define SALT_LEN 16
-#define SCRYPT_LEN 32
-
-/* definitions of flags in the structure below */
-#define CRYPT_MNT_KEY_UNENCRYPTED 0x1 /* The key for the partition is not encrypted. */
-#define CRYPT_ENCRYPTION_IN_PROGRESS \
- 0x2 /* Encryption partially completed, \
- encrypted_upto valid*/
-#define CRYPT_INCONSISTENT_STATE \
- 0x4 /* Set when starting encryption, clear when \
- exit cleanly, either through success or \
- correctly marked partial encryption */
-#define CRYPT_DATA_CORRUPT \
- 0x8 /* Set when encryption is fine, but the \
- underlying volume is corrupt */
-#define CRYPT_FORCE_ENCRYPTION \
- 0x10 /* Set when it is time to encrypt this \
- volume on boot. Everything in this \
- structure is set up correctly as \
- though device is encrypted except \
- that the master key is encrypted with the \
- default password. */
-#define CRYPT_FORCE_COMPLETE \
- 0x20 /* Set when the above encryption cycle is \
- complete. On next cryptkeeper entry, match \
- the password. If it matches fix the master \
- key and remove this flag. */
-
-/* Allowed values for type in the structure below */
-#define CRYPT_TYPE_PASSWORD \
- 0 /* master_key is encrypted with a password \
- * Must be zero to be compatible with pre-L \
- * devices where type is always password.*/
-#define CRYPT_TYPE_DEFAULT \
- 1 /* master_key is encrypted with default \
- * password */
-#define CRYPT_TYPE_PATTERN 2 /* master_key is encrypted with a pattern */
-#define CRYPT_TYPE_PIN 3 /* master_key is encrypted with a pin */
-#define CRYPT_TYPE_MAX_TYPE 3 /* type cannot be larger than this value */
-
-#define CRYPT_MNT_MAGIC 0xD0B5B1C4
-#define PERSIST_DATA_MAGIC 0xE950CD44
-
-/* Key Derivation Function algorithms */
-#define KDF_PBKDF2 1
-#define KDF_SCRYPT 2
-/* Algorithms 3 & 4 deprecated before shipping outside of google, so removed */
-#define KDF_SCRYPT_KEYMASTER 5
-
-/* Maximum allowed keymaster blob size. */
-#define KEYMASTER_BLOB_SIZE 2048
-
-/* __le32 and __le16 defined in system/extras/ext4_utils/ext4_utils.h */
-#define __le8 unsigned char
-
-#if !defined(SHA256_DIGEST_LENGTH)
-#define SHA256_DIGEST_LENGTH 32
-#endif
-
-/* This structure starts 16,384 bytes before the end of a hardware
- * partition that is encrypted, or in a separate partition. It's location
- * is specified by a property set in init.<device>.rc.
- * The structure allocates 48 bytes for a key, but the real key size is
- * specified in the struct. Currently, the code is hardcoded to use 128
- * bit keys.
- * The fields after salt are only valid in rev 1.1 and later stuctures.
- * Obviously, the filesystem does not include the last 16 kbytes
- * of the partition if the crypt_mnt_ftr lives at the end of the
- * partition.
- */
-
-struct crypt_mnt_ftr {
- __le32 magic; /* See above */
- __le16 major_version;
- __le16 minor_version;
- __le32 ftr_size; /* in bytes, not including key following */
- __le32 flags; /* See above */
- __le32 keysize; /* in bytes */
- __le32 crypt_type; /* how master_key is encrypted. Must be a
- * CRYPT_TYPE_XXX value */
- __le64 fs_size; /* Size of the encrypted fs, in 512 byte sectors */
- __le32 failed_decrypt_count; /* count of # of failed attempts to decrypt and
- mount, set to 0 on successful mount */
- unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption
- needed to decrypt this
- partition, null terminated */
- __le32 spare2; /* ignored */
- unsigned char master_key[MAX_KEY_LEN]; /* The encrypted key for decrypting the filesystem */
- unsigned char salt[SALT_LEN]; /* The salt used for this encryption */
- __le64 persist_data_offset[2]; /* Absolute offset to both copies of crypt_persist_data
- * on device with that info, either the footer of the
- * real_blkdevice or the metadata partition. */
-
- __le32 persist_data_size; /* The number of bytes allocated to each copy of the
- * persistent data table*/
-
- __le8 kdf_type; /* The key derivation function used. */
-
- /* scrypt parameters. See www.tarsnap.com/scrypt/scrypt.pdf */
- __le8 N_factor; /* (1 << N) */
- __le8 r_factor; /* (1 << r) */
- __le8 p_factor; /* (1 << p) */
- __le64 encrypted_upto; /* If we are in state CRYPT_ENCRYPTION_IN_PROGRESS and
- we have to stop (e.g. power low) this is the last
- encrypted 512 byte sector.*/
- __le8 hash_first_block[SHA256_DIGEST_LENGTH]; /* When CRYPT_ENCRYPTION_IN_PROGRESS
- set, hash of first block, used
- to validate before continuing*/
-
- /* key_master key, used to sign the derived key which is then used to generate
- * the intermediate key
- * This key should be used for no other purposes! We use this key to sign unpadded
- * data, which is acceptable but only if the key is not reused elsewhere. */
- __le8 keymaster_blob[KEYMASTER_BLOB_SIZE];
- __le32 keymaster_blob_size;
-
- /* Store scrypt of salted intermediate key. When decryption fails, we can
- check if this matches, and if it does, we know that the problem is with the
- drive, and there is no point in asking the user for more passwords.
-
- Note that if any part of this structure is corrupt, this will not match and
- we will continue to believe the user entered the wrong password. In that
- case the only solution is for the user to enter a password enough times to
- force a wipe.
-
- Note also that there is no need to worry about migration. If this data is
- wrong, we simply won't recognise a right password, and will continue to
- prompt. On the first password change, this value will be populated and
- then we will be OK.
- */
- unsigned char scrypted_intermediate_key[SCRYPT_LEN];
-
- /* sha of this structure with this element set to zero
- Used when encrypting on reboot to validate structure before doing something
- fatal
- */
- unsigned char sha256[SHA256_DIGEST_LENGTH];
-};
-
-/* Persistant data that should be available before decryption.
- * Things like airplane mode, locale and timezone are kept
- * here and can be retrieved by the CryptKeeper UI to properly
- * configure the phone before asking for the password
- * This is only valid if the major and minor version above
- * is set to 1.1 or higher.
- *
- * This is a 4K structure. There are 2 copies, and the code alternates
- * writing one and then clearing the previous one. The reading
- * code reads the first valid copy it finds, based on the magic number.
- * The absolute offset to the first of the two copies is kept in rev 1.1
- * and higher crypt_mnt_ftr structures.
- */
-struct crypt_persist_entry {
- char key[PROPERTY_KEY_MAX];
- char val[PROPERTY_VALUE_MAX];
-};
-
-/* Should be exactly 4K in size */
-struct crypt_persist_data {
- __le32 persist_magic;
- __le32 persist_valid_entries;
- __le32 persist_spare[30];
- struct crypt_persist_entry persist_entry[0];
-};
-
-static int wait_and_unmount(const char* mountpoint, bool kill);
-
-typedef int (*kdf_func)(const char* passwd, const unsigned char* salt, unsigned char* ikey,
- void* params);
-
-#define UNUSED __attribute__((unused))
-
-#define HASH_COUNT 2000
-
-constexpr size_t INTERMEDIATE_KEY_LEN_BYTES = 16;
-constexpr size_t INTERMEDIATE_IV_LEN_BYTES = 16;
-constexpr size_t INTERMEDIATE_BUF_SIZE = (INTERMEDIATE_KEY_LEN_BYTES + INTERMEDIATE_IV_LEN_BYTES);
-
-// SCRYPT_LEN is used by struct crypt_mnt_ftr for its intermediate key.
-static_assert(INTERMEDIATE_BUF_SIZE == SCRYPT_LEN, "Mismatch of intermediate key sizes");
-
-#define KEY_IN_FOOTER "footer"
-
-#define DEFAULT_PASSWORD "default_password"
-
-#define CRYPTO_BLOCK_DEVICE "userdata"
-
-#define BREADCRUMB_FILE "/data/misc/vold/convert_fde"
-
-#define EXT4_FS 1
-#define F2FS_FS 2
-
-#define TABLE_LOAD_RETRIES 10
-
-#define RSA_KEY_SIZE 2048
-#define RSA_KEY_SIZE_BYTES (RSA_KEY_SIZE / 8)
-#define RSA_EXPONENT 0x10001
-#define KEYMASTER_CRYPTFS_RATE_LIMIT 1 // Maximum one try per second
-
-#define RETRY_MOUNT_ATTEMPTS 10
-#define RETRY_MOUNT_DELAY_SECONDS 1
-
-#define CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE (1)
-
-static int put_crypt_ftr_and_key(struct crypt_mnt_ftr* crypt_ftr);
-
-static unsigned char saved_master_key[MAX_KEY_LEN];
-static char* saved_mount_point;
-static int master_key_saved = 0;
-static struct crypt_persist_data* persist_data = NULL;
-
-constexpr CryptoType aes_128_cbc = CryptoType()
- .set_config_name("AES-128-CBC")
- .set_kernel_name("aes-cbc-essiv:sha256")
- .set_keysize(16);
-
-constexpr CryptoType supported_crypto_types[] = {aes_128_cbc, ::adiantum};
-
-static_assert(validateSupportedCryptoTypes(MAX_KEY_LEN, supported_crypto_types,
- array_length(supported_crypto_types)),
- "We have a CryptoType with keysize > MAX_KEY_LEN or which was "
- "incompletely constructed.");
-
-static const CryptoType& get_crypto_type() {
- // We only want to parse this read-only property once. But we need to wait
- // until the system is initialized before we can read it. So we use a static
- // scoped within this function to get it only once.
- static CryptoType crypto_type =
- lookup_crypto_algorithm(supported_crypto_types, array_length(supported_crypto_types),
- aes_128_cbc, "ro.crypto.fde_algorithm");
- return crypto_type;
-}
-
-const KeyGeneration cryptfs_get_keygen() {
- return KeyGeneration{get_crypto_type().get_keysize(), true, false};
-}
-
-/* Should we use keymaster? */
-static int keymaster_check_compatibility() {
- return keymaster_compatibility_cryptfs_scrypt();
-}
-
-/* Create a new keymaster key and store it in this footer */
-static int keymaster_create_key(struct crypt_mnt_ftr* ftr) {
- if (ftr->keymaster_blob_size) {
- SLOGI("Already have key");
- return 0;
- }
-
- int rc = keymaster_create_key_for_cryptfs_scrypt(
- RSA_KEY_SIZE, RSA_EXPONENT, KEYMASTER_CRYPTFS_RATE_LIMIT, ftr->keymaster_blob,
- KEYMASTER_BLOB_SIZE, &ftr->keymaster_blob_size);
- if (rc) {
- if (ftr->keymaster_blob_size > KEYMASTER_BLOB_SIZE) {
- SLOGE("Keymaster key blob too large");
- ftr->keymaster_blob_size = 0;
- }
- SLOGE("Failed to generate keypair");
- return -1;
- }
- return 0;
-}
-
-/* This signs the given object using the keymaster key. */
-static int keymaster_sign_object(struct crypt_mnt_ftr* ftr, const unsigned char* object,
- const size_t object_size, unsigned char** signature,
- size_t* signature_size) {
- unsigned char to_sign[RSA_KEY_SIZE_BYTES];
- size_t to_sign_size = sizeof(to_sign);
- memset(to_sign, 0, RSA_KEY_SIZE_BYTES);
-
- // To sign a message with RSA, the message must satisfy two
- // constraints:
- //
- // 1. The message, when interpreted as a big-endian numeric value, must
- // be strictly less than the public modulus of the RSA key. Note
- // that because the most significant bit of the public modulus is
- // guaranteed to be 1 (else it's an (n-1)-bit key, not an n-bit
- // key), an n-bit message with most significant bit 0 always
- // satisfies this requirement.
- //
- // 2. The message must have the same length in bits as the public
- // modulus of the RSA key. This requirement isn't mathematically
- // necessary, but is necessary to ensure consistency in
- // implementations.
- switch (ftr->kdf_type) {
- case KDF_SCRYPT_KEYMASTER:
- // This ensures the most significant byte of the signed message
- // is zero. We could have zero-padded to the left instead, but
- // this approach is slightly more robust against changes in
- // object size. However, it's still broken (but not unusably
- // so) because we really should be using a proper deterministic
- // RSA padding function, such as PKCS1.
- memcpy(to_sign + 1, object, std::min((size_t)RSA_KEY_SIZE_BYTES - 1, object_size));
- SLOGI("Signing safely-padded object");
- break;
- default:
- SLOGE("Unknown KDF type %d", ftr->kdf_type);
- return -1;
- }
- for (;;) {
- auto result = keymaster_sign_object_for_cryptfs_scrypt(
- ftr->keymaster_blob, ftr->keymaster_blob_size, KEYMASTER_CRYPTFS_RATE_LIMIT, to_sign,
- to_sign_size, signature, signature_size);
- switch (result) {
- case KeymasterSignResult::ok:
- return 0;
- case KeymasterSignResult::upgrade:
- break;
- default:
- return -1;
- }
- SLOGD("Upgrading key");
- if (keymaster_upgrade_key_for_cryptfs_scrypt(
- RSA_KEY_SIZE, RSA_EXPONENT, KEYMASTER_CRYPTFS_RATE_LIMIT, ftr->keymaster_blob,
- ftr->keymaster_blob_size, ftr->keymaster_blob, KEYMASTER_BLOB_SIZE,
- &ftr->keymaster_blob_size) != 0) {
- SLOGE("Failed to upgrade key");
- return -1;
- }
- if (put_crypt_ftr_and_key(ftr) != 0) {
- SLOGE("Failed to write upgraded key to disk");
- }
- SLOGD("Key upgraded successfully");
- }
-}
-
-/* Store password when userdata is successfully decrypted and mounted.
- * Cleared by cryptfs_clear_password
- *
- * To avoid a double prompt at boot, we need to store the CryptKeeper
- * password and pass it to KeyGuard, which uses it to unlock KeyStore.
- * Since the entire framework is torn down and rebuilt after encryption,
- * we have to use a daemon or similar to store the password. Since vold
- * is secured against IPC except from system processes, it seems a reasonable
- * place to store this.
- *
- * password should be cleared once it has been used.
- *
- * password is aged out after password_max_age_seconds seconds.
- */
-static char* password = 0;
-static int password_expiry_time = 0;
-static const int password_max_age_seconds = 60;
-
-enum class RebootType { reboot, recovery, shutdown };
-static void cryptfs_reboot(RebootType rt) {
- switch (rt) {
- case RebootType::reboot:
- property_set(ANDROID_RB_PROPERTY, "reboot");
- break;
-
- case RebootType::recovery:
- property_set(ANDROID_RB_PROPERTY, "reboot,recovery");
- break;
-
- case RebootType::shutdown:
- property_set(ANDROID_RB_PROPERTY, "shutdown");
- break;
- }
-
- sleep(20);
-
- /* Shouldn't get here, reboot should happen before sleep times out */
- return;
-}
-
-/**
- * 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) {
- char paramstr[PROPERTY_VALUE_MAX];
- int Nf, rf, pf;
-
- property_get(SCRYPT_PROP, paramstr, SCRYPT_DEFAULTS);
- if (!parse_scrypt_parameters(paramstr, &Nf, &rf, &pf)) {
- SLOGW("bad scrypt parameters '%s' should be like '12:8:1'; using defaults", paramstr);
- parse_scrypt_parameters(SCRYPT_DEFAULTS, &Nf, &rf, &pf);
- }
- ftr->N_factor = Nf;
- ftr->r_factor = rf;
- ftr->p_factor = pf;
-}
-
-static uint64_t get_fs_size(const char* dev) {
- int fd, block_size;
- struct ext4_super_block sb;
- uint64_t len;
-
- if ((fd = open(dev, O_RDONLY | O_CLOEXEC)) < 0) {
- SLOGE("Cannot open device to get filesystem size ");
- return 0;
- }
-
- if (lseek64(fd, 1024, SEEK_SET) < 0) {
- SLOGE("Cannot seek to superblock");
- return 0;
- }
-
- if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
- SLOGE("Cannot read superblock");
- return 0;
- }
-
- close(fd);
-
- if (le32_to_cpu(sb.s_magic) != EXT4_SUPER_MAGIC) {
- SLOGE("Not a valid ext4 superblock");
- return 0;
- }
- block_size = 1024 << sb.s_log_block_size;
- /* compute length in bytes */
- len = (((uint64_t)sb.s_blocks_count_hi << 32) + sb.s_blocks_count_lo) * block_size;
-
- /* return length in sectors */
- return len / 512;
-}
-
-static void get_crypt_info(std::string* key_loc, std::string* real_blk_device) {
- for (const auto& entry : fstab_default) {
- if (!entry.fs_mgr_flags.vold_managed &&
- (entry.fs_mgr_flags.crypt || entry.fs_mgr_flags.force_crypt ||
- entry.fs_mgr_flags.force_fde_or_fbe || entry.fs_mgr_flags.file_encryption)) {
- if (key_loc != nullptr) {
- *key_loc = entry.key_loc;
- }
- if (real_blk_device != nullptr) {
- *real_blk_device = entry.blk_device;
- }
- return;
- }
- }
-}
-
-static int get_crypt_ftr_info(char** metadata_fname, off64_t* off) {
- static int cached_data = 0;
- static uint64_t cached_off = 0;
- static char cached_metadata_fname[PROPERTY_VALUE_MAX] = "";
- char key_loc[PROPERTY_VALUE_MAX];
- char real_blkdev[PROPERTY_VALUE_MAX];
- int rc = -1;
-
- if (!cached_data) {
- std::string key_loc;
- std::string real_blkdev;
- get_crypt_info(&key_loc, &real_blkdev);
-
- if (key_loc == KEY_IN_FOOTER) {
- if (::GetBlockDevSize(real_blkdev, &cached_off) == android::OK) {
- /* 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.c_str(), sizeof(cached_metadata_fname));
- cached_off -= CRYPT_FOOTER_OFFSET;
- cached_data = 1;
- } else {
- SLOGE("Cannot get size of block device %s\n", real_blkdev.c_str());
- }
- } else {
- strlcpy(cached_metadata_fname, key_loc.c_str(), 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;
-}
-
-/* Set sha256 checksum in structure */
-static void set_ftr_sha(struct crypt_mnt_ftr* crypt_ftr) {
- SHA256_CTX c;
- SHA256_Init(&c);
- memset(crypt_ftr->sha256, 0, sizeof(crypt_ftr->sha256));
- SHA256_Update(&c, crypt_ftr, sizeof(*crypt_ftr));
- SHA256_Final(crypt_ftr->sha256, &c);
-}
-
-/* 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 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;
-
- set_ftr_sha(crypt_ftr);
-
- if (get_crypt_ftr_info(&fname, &starting_off)) {
- SLOGE("Unable to get crypt_ftr_info\n");
- return -1;
- }
- if (fname[0] != '/') {
- SLOGE("put_crypt_ftr_and_key::Unexpected value for crypto key location: %s\n", fname);
- return -1;
- }
- if ((fd = open(fname, O_RDWR | O_CREAT | O_CLOEXEC, 0600)) < 0) {
- SLOGE("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) {
- SLOGE("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)) {
- SLOGE("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)) {
- SLOGE("Cannot set footer file size\n");
- goto errout;
- }
- }
-
- /* Success! */
- rc = 0;
-
-errout:
- close(fd);
- return rc;
-}
-
-static bool check_ftr_sha(const struct crypt_mnt_ftr* crypt_ftr) {
- struct crypt_mnt_ftr copy;
- memcpy(©, crypt_ftr, sizeof(copy));
- set_ftr_sha(©);
- return memcmp(copy.sha256, crypt_ftr->sha256, sizeof(copy.sha256)) == 0;
-}
-
-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;
-
- 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;
-
- SLOGW("upgrading crypto footer to 1.1");
-
- pdata = (crypt_persist_data*)malloc(CRYPT_PERSIST_DATA_SIZE);
- if (pdata == NULL) {
- SLOGE("Cannot allocate persisent data\n");
- return;
- }
- memset(pdata, 0, CRYPT_PERSIST_DATA_SIZE);
-
- /* Need to initialize the persistent data area */
- if (lseek64(fd, pdata_offset, SEEK_SET) == -1) {
- SLOGE("Cannot seek to persisent data offset\n");
- free(pdata);
- 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;
- free(pdata);
- }
-
- if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 1)) {
- SLOGW("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)) {
- SLOGW("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) {
- SLOGE("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 cnt;
- off64_t starting_off;
- int rc = -1;
- char* fname = NULL;
- struct stat statbuf;
-
- if (get_crypt_ftr_info(&fname, &starting_off)) {
- SLOGE("Unable to get crypt_ftr_info\n");
- return -1;
- }
- if (fname[0] != '/') {
- SLOGE("get_crypt_ftr_and_key::Unexpected value for crypto key location: %s\n", fname);
- return -1;
- }
- if ((fd = open(fname, O_RDWR | O_CLOEXEC)) < 0) {
- SLOGE("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)) {
- SLOGE("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) {
- SLOGE("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)) {
- SLOGE("Cannot read real block device footer\n");
- goto errout;
- }
-
- if (crypt_ftr->magic != CRYPT_MNT_MAGIC) {
- SLOGE("Bad magic for real block device %s\n", fname);
- goto errout;
- }
-
- if (crypt_ftr->major_version != CURRENT_MAJOR_VERSION) {
- SLOGE("Cannot understand major version %d real block device footer; expected %d\n",
- crypt_ftr->major_version, CURRENT_MAJOR_VERSION);
- goto errout;
- }
-
- // We risk buffer overflows with oversized keys, so we just reject them.
- // 0-sized keys are problematic (essentially by-passing encryption), and
- // AES-CBC key wrapping only works for multiples of 16 bytes.
- if ((crypt_ftr->keysize == 0) || ((crypt_ftr->keysize % 16) != 0) ||
- (crypt_ftr->keysize > MAX_KEY_LEN)) {
- SLOGE(
- "Invalid keysize (%u) for block device %s; Must be non-zero, "
- "divisible by 16, and <= %d\n",
- crypt_ftr->keysize, fname, MAX_KEY_LEN);
- goto errout;
- }
-
- if (crypt_ftr->minor_version > CURRENT_MINOR_VERSION) {
- SLOGW("Warning: crypto footer minor version %d, expected <= %d, continuing...\n",
- crypt_ftr->minor_version, CURRENT_MINOR_VERSION);
- }
-
- /* If this is a verion 1.0 crypt_ftr, make it a 1.1 crypt footer, and update the
- * copy on disk before returning.
- */
- if (crypt_ftr->minor_version < 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]) {
- SLOGE("Crypt_ftr persist data regions overlap");
- return -1;
- }
-
- if (crypt_ftr->persist_data_offset[0] >= crypt_ftr->persist_data_offset[1]) {
- SLOGE("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) {
- SLOGE("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 = (crypt_persist_data*)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)) {
- SLOGE("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 | O_CLOEXEC);
- if (fd < 0) {
- SLOGE("Cannot open %s metadata file", fname);
- return -1;
- }
-
- pdata = (crypt_persist_data*)malloc(crypt_ftr.persist_data_size);
- if (pdata == NULL) {
- SLOGE("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) {
- SLOGE("Cannot seek to read persistent data on %s", fname);
- goto err2;
- }
- if (unix_read(fd, pdata, crypt_ftr.persist_data_size) < 0) {
- SLOGE("Error reading persistent data on iteration %d", i);
- goto err2;
- }
- if (pdata->persist_magic == PERSIST_DATA_MAGIC) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- SLOGI("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 fd;
- int ret;
-
- if (persist_data == NULL) {
- SLOGE("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)) {
- SLOGE("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 | O_CLOEXEC);
- if (fd < 0) {
- SLOGE("Cannot open %s metadata file", fname);
- return -1;
- }
-
- pdata = (crypt_persist_data*)malloc(crypt_ftr.persist_data_size);
- if (pdata == NULL) {
- SLOGE("Cannot allocate persistant data");
- goto err;
- }
-
- if (lseek64(fd, crypt_ftr.persist_data_offset[0], SEEK_SET) < 0) {
- SLOGE("Cannot seek to read persistent data on %s", fname);
- goto err2;
- }
-
- if (unix_read(fd, pdata, crypt_ftr.persist_data_size) < 0) {
- SLOGE("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 (lseek64(fd, write_offset, SEEK_SET) < 0) {
- SLOGE("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 (lseek64(fd, erase_offset, SEEK_SET) < 0) {
- SLOGE("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) {
- SLOGE("Cannot write to erase previous persistent data");
- goto err2;
- }
- fsync(fd);
- } else {
- SLOGE("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
- */
-static void convert_key_to_hex_ascii(const 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';
-}
-
-/*
- * If the ro.crypto.fde_sector_size system property is set, append the
- * parameters to make dm-crypt use the specified crypto sector size and round
- * the crypto device size down to a crypto sector boundary.
- */
-static int add_sector_size_param(DmTargetCrypt* target, struct crypt_mnt_ftr* ftr) {
- constexpr char DM_CRYPT_SECTOR_SIZE[] = "ro.crypto.fde_sector_size";
- char value[PROPERTY_VALUE_MAX];
-
- if (property_get(DM_CRYPT_SECTOR_SIZE, value, "") > 0) {
- unsigned int sector_size;
-
- if (!ParseUint(value, §or_size) || sector_size < 512 || sector_size > 4096 ||
- (sector_size & (sector_size - 1)) != 0) {
- SLOGE("Invalid value for %s: %s. Must be >= 512, <= 4096, and a power of 2\n",
- DM_CRYPT_SECTOR_SIZE, value);
- return -1;
- }
-
- target->SetSectorSize(sector_size);
-
- // With this option, IVs will match the sector numbering, instead
- // of being hard-coded to being based on 512-byte sectors.
- target->SetIvLargeSectors();
-
- // Round the crypto device size down to a crypto sector boundary.
- ftr->fs_size &= ~((sector_size / 512) - 1);
- }
- return 0;
-}
-
-static int create_crypto_blk_dev(struct crypt_mnt_ftr* crypt_ftr, const unsigned char* master_key,
- const char* real_blk_name, std::string* crypto_blk_name,
- const char* name, uint32_t flags) {
- auto& dm = DeviceMapper::Instance();
- ALOGE("create_crypto_blk_dev\n");
-
- // We need two ASCII characters to represent each byte, and need space for
- // the '\0' terminator.
- char master_key_ascii[MAX_KEY_LEN * 2 + 1];
- convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
-
- auto target = std::make_unique<DmTargetCrypt>(0, crypt_ftr->fs_size,
- (const char*)crypt_ftr->crypto_type_name,
- master_key_ascii, 0, real_blk_name, 0);
- target->AllowDiscards();
-
- if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE) {
- target->AllowEncryptOverride();
- }
- if (add_sector_size_param(target.get(), crypt_ftr)) {
- SLOGE("Error processing dm-crypt sector size param\n");
- return -1;
- }
-
- DmTable table;
- table.AddTarget(std::move(target));
-
- int load_count = 1;
- while (load_count < TABLE_LOAD_RETRIES) {
- if (dm.CreateDevice(name, table)) {
- break;
- }
- load_count++;
- }
-
- if (load_count >= TABLE_LOAD_RETRIES) {
- SLOGE("Cannot load dm-crypt mapping table.\n");
- return -1;
- }
- if (load_count > 1) {
- SLOGI("Took %d tries to load dmcrypt table.\n", load_count);
- }
-
- // ALOGE("GetDmDevicePathByName::%s::%s\n", name, crypto_blk_name->c_str());
- if (!dm.GetDmDevicePathByName(name, crypto_blk_name)) {
- SLOGE("Cannot determine dm-crypt path for %s.\n", name);
- return -1;
- }
-
- /* Ensure the dm device has been created before returning. */
- if (::WaitForFile(crypto_blk_name->c_str(), 1s) < 0) {
- // WaitForFile generates a suitable log message
- return -1;
- }
- return 0;
-}
-
-static int delete_crypto_blk_dev(const std::string& name) {
- bool ret;
- auto& dm = DeviceMapper::Instance();
- // TODO(b/149396179) there appears to be a race somewhere in the system where trying
- // to delete the device fails with EBUSY; for now, work around this by retrying.
- int tries = 5;
- while (tries-- > 0) {
- ret = dm.DeleteDevice(name);
- if (ret || errno != EBUSY) {
- break;
- }
- SLOGW("DM_DEV Cannot remove dm-crypt device %s: %s, retrying...\n", name.c_str(),
- strerror(errno));
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
- if (!ret) {
- SLOGE("DM_DEV Cannot remove dm-crypt device %s: %s\n", name.c_str(), strerror(errno));
- return -1;
- }
- return 0;
-}
-
-static int pbkdf2(const char* passwd, const unsigned char* salt, unsigned char* ikey,
- void* params UNUSED) {
- SLOGI("Using pbkdf2 for cryptfs KDF");
-
- /* Turn the password into a key and IV that can decrypt the master key */
- return PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), salt, SALT_LEN, HASH_COUNT,
- INTERMEDIATE_BUF_SIZE, ikey) != 1;
-}
-
-static int scrypt(const char* passwd, const unsigned char* salt, unsigned char* ikey, void* params) {
- SLOGI("Using scrypt for cryptfs KDF");
-
- 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((const uint8_t*)passwd, strlen(passwd), salt, SALT_LEN, N, r, p, ikey,
- INTERMEDIATE_BUF_SIZE);
-
- return 0;
-}
-
-static int scrypt_keymaster(const char* passwd, const unsigned char* salt, unsigned char* ikey,
- void* params) {
- SLOGI("Using scrypt with keymaster for cryptfs KDF");
-
- int rc;
- size_t signature_size;
- unsigned char* signature;
- 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;
-
- rc = crypto_scrypt((const uint8_t*)passwd, strlen(passwd), salt, SALT_LEN, N, r, p, ikey,
- INTERMEDIATE_BUF_SIZE);
-
- if (rc) {
- SLOGE("scrypt failed");
- return -1;
- }
-
- if (keymaster_sign_object(ftr, ikey, INTERMEDIATE_BUF_SIZE, &signature, &signature_size)) {
- SLOGE("Signing failed");
- return -1;
- }
-
- rc = crypto_scrypt(signature, signature_size, salt, SALT_LEN, N, r, p, ikey,
- INTERMEDIATE_BUF_SIZE);
- free(signature);
-
- if (rc) {
- SLOGE("scrypt failed");
- return -1;
- }
-
- return 0;
-}
-
-static int encrypt_master_key(const char* passwd, const unsigned char* salt,
- const unsigned char* decrypted_master_key,
- unsigned char* encrypted_master_key, struct crypt_mnt_ftr* crypt_ftr) {
- unsigned char ikey[INTERMEDIATE_BUF_SIZE] = {0};
- EVP_CIPHER_CTX e_ctx;
- int encrypted_len, final_len;
- int rc = 0;
-
- /* Turn the password into an intermediate key and IV that can decrypt the master key */
- get_device_scrypt_params(crypt_ftr);
-
- switch (crypt_ftr->kdf_type) {
- case KDF_SCRYPT_KEYMASTER:
- if (keymaster_create_key(crypt_ftr)) {
- SLOGE("keymaster_create_key failed");
- return -1;
- }
-
- if (scrypt_keymaster(passwd, salt, ikey, crypt_ftr)) {
- SLOGE("scrypt failed");
- return -1;
- }
- break;
-
- case KDF_SCRYPT:
- if (scrypt(passwd, salt, ikey, crypt_ftr)) {
- SLOGE("scrypt failed");
- return -1;
- }
- break;
-
- default:
- SLOGE("Invalid kdf_type");
- return -1;
- }
-
- /* Initialize the decryption engine */
- EVP_CIPHER_CTX_init(&e_ctx);
- if (!EVP_EncryptInit_ex(&e_ctx, EVP_aes_128_cbc(), NULL, ikey,
- ikey + INTERMEDIATE_KEY_LEN_BYTES)) {
- SLOGE("EVP_EncryptInit failed\n");
- return -1;
- }
- EVP_CIPHER_CTX_set_padding(&e_ctx, 0); /* Turn off padding as our data is block aligned */
-
- /* Encrypt the master key */
- if (!EVP_EncryptUpdate(&e_ctx, encrypted_master_key, &encrypted_len, decrypted_master_key,
- crypt_ftr->keysize)) {
- SLOGE("EVP_EncryptUpdate failed\n");
- return -1;
- }
- if (!EVP_EncryptFinal_ex(&e_ctx, encrypted_master_key + encrypted_len, &final_len)) {
- SLOGE("EVP_EncryptFinal failed\n");
- return -1;
- }
-
- if (encrypted_len + final_len != static_cast<int>(crypt_ftr->keysize)) {
- SLOGE("EVP_Encryption length check failed with %d, %d bytes\n", encrypted_len, final_len);
- return -1;
- }
-
- /* Store the scrypt of the intermediate key, so we can validate if it's a
- password error or mount error when things go wrong.
- Note there's no need to check for errors, since if this is incorrect, we
- simply won't wipe userdata, which is the correct default behavior
- */
- int N = 1 << crypt_ftr->N_factor;
- int r = 1 << crypt_ftr->r_factor;
- int p = 1 << crypt_ftr->p_factor;
-
- rc = crypto_scrypt(ikey, INTERMEDIATE_KEY_LEN_BYTES, crypt_ftr->salt, sizeof(crypt_ftr->salt),
- N, r, p, crypt_ftr->scrypted_intermediate_key,
- sizeof(crypt_ftr->scrypted_intermediate_key));
-
- if (rc) {
- SLOGE("encrypt_master_key: crypto_scrypt failed");
- }
-
- EVP_CIPHER_CTX_cleanup(&e_ctx);
-
- return 0;
-}
-
-static int decrypt_master_key_aux(const char* passwd, unsigned char* salt,
- const unsigned char* encrypted_master_key, size_t keysize,
- unsigned char* decrypted_master_key, kdf_func kdf,
- void* kdf_params, unsigned char** intermediate_key,
- size_t* intermediate_key_size) {
- unsigned char ikey[INTERMEDIATE_BUF_SIZE] = {0};
- EVP_CIPHER_CTX d_ctx;
- int decrypted_len, final_len;
-
- /* Turn the password into an intermediate key and IV that can decrypt the
- master key */
- if (kdf(passwd, salt, ikey, kdf_params)) {
- SLOGE("kdf failed");
- return -1;
- }
-
- /* Initialize the decryption engine */
- EVP_CIPHER_CTX_init(&d_ctx);
- if (!EVP_DecryptInit_ex(&d_ctx, EVP_aes_128_cbc(), NULL, ikey,
- ikey + INTERMEDIATE_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,
- keysize)) {
- return -1;
- }
- if (!EVP_DecryptFinal_ex(&d_ctx, decrypted_master_key + decrypted_len, &final_len)) {
- return -1;
- }
-
- if (decrypted_len + final_len != static_cast<int>(keysize)) {
- return -1;
- }
-
- /* Copy intermediate key if needed by params */
- if (intermediate_key && intermediate_key_size) {
- *intermediate_key = (unsigned char*)malloc(INTERMEDIATE_KEY_LEN_BYTES);
- if (*intermediate_key) {
- memcpy(*intermediate_key, ikey, INTERMEDIATE_KEY_LEN_BYTES);
- *intermediate_key_size = INTERMEDIATE_KEY_LEN_BYTES;
- }
- }
-
- EVP_CIPHER_CTX_cleanup(&d_ctx);
-
- return 0;
-}
-
-static void get_kdf_func(struct crypt_mnt_ftr* ftr, kdf_func* kdf, void** kdf_params) {
- if (ftr->kdf_type == KDF_SCRYPT_KEYMASTER) {
- *kdf = scrypt_keymaster;
- *kdf_params = ftr;
- } else if (ftr->kdf_type == KDF_SCRYPT) {
- *kdf = scrypt;
- *kdf_params = ftr;
- } else {
- *kdf = pbkdf2;
- *kdf_params = NULL;
- }
-}
-
-static int decrypt_master_key(const char* passwd, unsigned char* decrypted_master_key,
- struct crypt_mnt_ftr* crypt_ftr, unsigned char** intermediate_key,
- size_t* intermediate_key_size) {
- kdf_func kdf;
- void* kdf_params;
- int ret;
-
- get_kdf_func(crypt_ftr, &kdf, &kdf_params);
- ret = decrypt_master_key_aux(passwd, crypt_ftr->salt, crypt_ftr->master_key, crypt_ftr->keysize,
- decrypted_master_key, kdf, kdf_params, intermediate_key,
- intermediate_key_size);
- if (ret != 0) {
- SLOGW("failure decrypting master key");
- }
-
- return ret;
-}
-
-static int create_encrypted_random_key(const char* passwd, unsigned char* master_key,
- unsigned char* salt, struct crypt_mnt_ftr* crypt_ftr) {
- unsigned char key_buf[MAX_KEY_LEN];
-
- /* Get some random bits for a key and salt */
- if (::ReadRandomBytes(sizeof(key_buf), reinterpret_cast<char*>(key_buf)) != 0) {
- return -1;
- }
- if (::ReadRandomBytes(SALT_LEN, reinterpret_cast<char*>(salt)) != 0) {
- return -1;
- }
-
- /* Now encrypt it with the password */
- return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr);
-}
-
-static void ensure_subdirectory_unmounted(const char *prefix) {
- std::vector<std::string> umount_points;
- std::unique_ptr<FILE, int (*)(FILE*)> mnts(setmntent("/proc/mounts", "r"), endmntent);
- if (!mnts) {
- SLOGW("could not read mount files");
- return;
- }
-
- //Find sudirectory mount point
- mntent* mentry;
- std::string top_directory(prefix);
- if (!android::base::EndsWith(prefix, "/")) {
- top_directory = top_directory + "/";
- }
- while ((mentry = getmntent(mnts.get())) != nullptr) {
- if (strcmp(mentry->mnt_dir, top_directory.c_str()) == 0) {
- continue;
- }
-
- if (android::base::StartsWith(mentry->mnt_dir, top_directory)) {
- SLOGW("found sub-directory mount %s - %s\n", prefix, mentry->mnt_dir);
- umount_points.push_back(mentry->mnt_dir);
- }
- }
-
- //Sort by path length to umount longest path first
- std::sort(std::begin(umount_points), std::end(umount_points),
- [](const std::string& s1, const std::string& s2) {return s1.length() > s2.length(); });
-
- for (std::string& mount_point : umount_points) {
- umount(mount_point.c_str());
- SLOGW("umount sub-directory mount %s\n", mount_point.c_str());
- }
-}
-
-static int wait_and_unmount(const char* mountpoint, bool kill) {
- int i, err, rc;
-
- // Subdirectory mount will cause a failure of umount.
- ensure_subdirectory_unmounted(mountpoint);
-#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)) {
- SLOGW("sending SIGHUP to processes with open files\n");
- android::vold::KillProcessesWithOpenFiles(mountpoint, SIGTERM);
- } else if (i == (WAIT_UNMOUNT_COUNT - 2)) {
- SLOGW("sending SIGKILL to processes with open files\n");
- android::vold::KillProcessesWithOpenFiles(mountpoint, SIGKILL);
- }
- }
-
- sleep(1);
- }
-
- if (i < WAIT_UNMOUNT_COUNT) {
- SLOGD("unmounting %s succeeded\n", mountpoint);
- rc = 0;
- } else {
- android::vold::KillProcessesWithOpenFiles(mountpoint, 0);
- SLOGE("unmounting %s failed: %s\n", mountpoint, strerror(err));
- rc = -1;
- }
-
- return rc;
-}
-
-static void prep_data_fs(void) {
- // NOTE: post_fs_data results in init calling back around to vold, so all
- // callers to this method must be async
-
- /* Do the prep of the /data filesystem */
- property_set("vold.post_fs_data_done", "0");
- property_set("vold.decrypt", "trigger_post_fs_data");
- SLOGD("Just triggered post_fs_data");
-
- /* Wait a max of 50 seconds, hopefully it takes much less */
- while (!android::base::WaitForProperty("vold.post_fs_data_done", "1", std::chrono::seconds(15))) {
- /* We timed out to prep /data in time. Continue wait. */
- SLOGE("waited 15s for vold.post_fs_data_done, still waiting...");
- }
- SLOGD("post_fs_data done");
-}
-
-static void cryptfs_set_corrupt() {
- // Mark the footer as bad
- struct crypt_mnt_ftr crypt_ftr;
- if (get_crypt_ftr_and_key(&crypt_ftr)) {
- SLOGE("Failed to get crypto footer - panic");
- return;
- }
-
- crypt_ftr.flags |= CRYPT_DATA_CORRUPT;
- if (put_crypt_ftr_and_key(&crypt_ftr)) {
- SLOGE("Failed to set crypto footer - panic");
- return;
- }
-}
-
-static void cryptfs_trigger_restart_min_framework() {
- if (fs_mgr_do_tmpfs_mount(DATA_MNT_POINT)) {
- SLOGE("Failed to mount tmpfs on data - panic");
- return;
- }
-
- if (property_set("vold.decrypt", "trigger_post_fs_data")) {
- SLOGE("Failed to trigger post fs data - panic");
- return;
- }
-
- if (property_set("vold.decrypt", "trigger_restart_min_framework")) {
- SLOGE("Failed to trigger restart min framework - panic");
- return;
- }
-}
-
-/* returns < 0 on failure */
-static int cryptfs_restart_internal(int restart_main) {
- char crypto_blkdev[MAXPATHLEN];
- int rc = -1;
- static int restart_successful = 0;
-
- /* Validate that it's OK to call this routine */
- if (!master_key_saved) {
- SLOGE("Encrypted filesystem not validated, aborting");
- return -1;
- }
-
- if (restart_successful) {
- SLOGE("System already restarted with encrypted disk, aborting");
- return -1;
- }
-
- if (restart_main) {
- /* Here is where we shut down the framework. The init scripts
- * start all services in one of these classes: core, early_hal, hal,
- * main and late_start. To get to the minimal UI for PIN entry, we
- * need to start core, early_hal, hal and main. When we want to
- * shutdown the framework again, we need to stop most of the services in
- * these classes, but only those services that were started after
- * /data was mounted. This excludes critical services like vold and
- * ueventd, which need to keep running. We could possible stop
- * even fewer services, but because we want services to pick up APEX
- * libraries from the real /data, restarting is better, as it makes
- * these devices consistent with FBE devices and lets them use the
- * most recent code.
- *
- * Once these services have stopped, we should be able
- * to umount the tmpfs /data, then mount the encrypted /data.
- * We then restart the class core, hal, 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 right set of services when
- * vold.decrypt is set to trigger_shutdown_framework.
- */
- property_set("vold.decrypt", "trigger_shutdown_framework");
- SLOGD("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) {
- SLOGE("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 && std::stoi(ro_prop)) {
- auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
- if (entry != nullptr) {
- entry->flags |= MS_RDONLY;
- }
- }
-
- /* If that succeeded, then mount the decrypted filesystem */
- int retries = RETRY_MOUNT_ATTEMPTS;
- int mount_rc;
-
- /*
- * fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
- * partitions in the fsck domain.
- */
- if (setexeccon(::sFsckContext)) {
- SLOGE("Failed to setexeccon");
- return -1;
- }
- bool needs_cp = ::cp_needsCheckpoint();
- while ((mount_rc = fs_mgr_do_mount(&fstab_default, DATA_MNT_POINT, crypto_blkdev, 0,
- needs_cp, false)) != 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 ) */
- SLOGI("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(RebootType::reboot);
- }
- } else {
- SLOGE("Failed to mount decrypted data");
- cryptfs_set_corrupt();
- cryptfs_trigger_restart_min_framework();
- SLOGI("Started framework to offer wipe");
- if (setexeccon(NULL)) {
- SLOGE("Failed to setexeccon");
- }
- return -1;
- }
- }
- if (setexeccon(NULL)) {
- SLOGE("Failed to setexeccon");
- return -1;
- }
-
- /* Create necessary paths on /data */
- prep_data_fs();
- property_set("vold.decrypt", "trigger_load_persist_props");
-
- /* startup service classes main and late_start */
- property_set("vold.decrypt", "trigger_restart_framework");
- SLOGD("Just triggered restart_framework\n");
-
- /* Give it a few moments to get started */
- sleep(1);
- }
-
- if (rc == 0) {
- restart_successful = 1;
- }
-
- return rc;
-}
-
-int cryptfs_restart(void) {
- SLOGI("cryptfs_restart");
- if (fscrypt_is_native()) {
- SLOGE("cryptfs_restart not valid for file encryption:");
- return -1;
- }
-
- /* Call internal implementation forcing a restart of main service group */
- return cryptfs_restart_internal(1);
-}
-
-static int do_crypto_complete(const char* mount_point) {
- struct crypt_mnt_ftr crypt_ftr;
- char encrypted_state[PROPERTY_VALUE_MAX];
-
- property_get("ro.crypto.state", encrypted_state, "");
- if (strcmp(encrypted_state, "encrypted")) {
- SLOGE("not running with encryption, aborting");
- return CRYPTO_COMPLETE_NOT_ENCRYPTED;
- }
-
- // crypto_complete is full disk encrypted status
- if (fscrypt_is_native()) {
- return CRYPTO_COMPLETE_NOT_ENCRYPTED;
- }
-
- if (get_crypt_ftr_and_key(&crypt_ftr)) {
- std::string key_loc;
- get_crypt_info(&key_loc, nullptr);
-
- /*
- * 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.empty() && key_loc[0] == '/' && (access("key_loc", F_OK) == -1)) {
- SLOGE("master key file does not exist, aborting");
- return CRYPTO_COMPLETE_NOT_ENCRYPTED;
- } else {
- SLOGE("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) {
- SLOGE("Encryption process is partway completed\n");
- return CRYPTO_COMPLETE_PARTIAL;
- }
-
- if (crypt_ftr.flags & CRYPT_INCONSISTENT_STATE) {
- SLOGE("Encryption process was interrupted but cannot continue\n");
- return CRYPTO_COMPLETE_INCONSISTENT;
- }
-
- if (crypt_ftr.flags & CRYPT_DATA_CORRUPT) {
- SLOGE("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, const char* passwd,
- const char* mount_point, const char* label) {
- unsigned char decrypted_master_key[MAX_KEY_LEN];
- std::string crypto_blkdev;
- std::string real_blkdev;
- char tmp_mount_point[64];
- unsigned int orig_failed_decrypt_count;
- int rc;
- int use_keymaster = 0;
- int upgrade = 0;
- unsigned char* intermediate_key = 0;
- size_t intermediate_key_size = 0;
- int N = 1 << crypt_ftr->N_factor;
- int r = 1 << crypt_ftr->r_factor;
- int p = 1 << crypt_ftr->p_factor;
-
- SLOGD("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)) {
- if (decrypt_master_key(passwd, decrypted_master_key, crypt_ftr, &intermediate_key,
- &intermediate_key_size)) {
- SLOGE("Failed to decrypt master key\n");
- rc = -1;
- goto errout;
- }
- }
-
- get_crypt_info(nullptr, &real_blkdev);
-
- // Create crypto block device - all (non fatal) code paths
- // need it
- if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key, real_blkdev.c_str(), &crypto_blkdev,
- label, 0)) {
- SLOGE("Error creating decrypted block device\n");
- rc = -1;
- goto errout;
- }
-
- /* Work out if the problem is the password or the data */
- unsigned char scrypted_intermediate_key[sizeof(crypt_ftr->scrypted_intermediate_key)];
-
- rc = crypto_scrypt(intermediate_key, intermediate_key_size, crypt_ftr->salt,
- sizeof(crypt_ftr->salt), N, r, p, scrypted_intermediate_key,
- sizeof(scrypted_intermediate_key));
-
- // Does the key match the crypto footer?
- if (rc == 0 && memcmp(scrypted_intermediate_key, crypt_ftr->scrypted_intermediate_key,
- sizeof(scrypted_intermediate_key)) == 0) {
- SLOGI("Password matches");
- rc = 0;
- } else {
- /* Try mounting the file system anyway, just in case the problem's with
- * the footer, not the key. */
- snprintf(tmp_mount_point, sizeof(tmp_mount_point), "%s/tmp_mnt", mount_point);
- mkdir(tmp_mount_point, 0755);
- if (fs_mgr_do_mount(&fstab_default, DATA_MNT_POINT,
- const_cast<char*>(crypto_blkdev.c_str()), tmp_mount_point)) {
- SLOGE("Error temp mounting decrypted block device\n");
- delete_crypto_blk_dev(label);
-
- rc = ++crypt_ftr->failed_decrypt_count;
- put_crypt_ftr_and_key(crypt_ftr);
- } else {
- /* Success! */
- SLOGI("Password did not match but decrypted drive mounted - continue");
- umount(tmp_mount_point);
- rc = 0;
- }
- }
-
- if (rc == 0) {
- crypt_ftr->failed_decrypt_count = 0;
- if (orig_failed_decrypt_count != 0) {
- put_crypt_ftr_and_key(crypt_ftr);
- }
-
- /* 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.c_str());
-
- /* Also save a the master key so we can reencrypted the key
- * the key when we want to change the password on it. */
- memcpy(saved_master_key, decrypted_master_key, crypt_ftr->keysize);
- saved_mount_point = strdup(mount_point);
- master_key_saved = 1;
- SLOGD("%s(): Master key saved\n", __FUNCTION__);
- rc = 0;
-
- // Upgrade if we're not using the latest KDF.
- use_keymaster = keymaster_check_compatibility();
- if (crypt_ftr->kdf_type == KDF_SCRYPT_KEYMASTER) {
- // Don't allow downgrade
- } else if (use_keymaster == 1 && crypt_ftr->kdf_type != KDF_SCRYPT_KEYMASTER) {
- crypt_ftr->kdf_type = KDF_SCRYPT_KEYMASTER;
- upgrade = 1;
- } else if (use_keymaster == 0 && crypt_ftr->kdf_type != KDF_SCRYPT) {
- crypt_ftr->kdf_type = KDF_SCRYPT;
- upgrade = 1;
- }
-
- if (upgrade) {
- rc = encrypt_master_key(passwd, crypt_ftr->salt, saved_master_key,
- crypt_ftr->master_key, crypt_ftr);
- if (!rc) {
- rc = put_crypt_ftr_and_key(crypt_ftr);
- }
- SLOGD("Key Derivation Function upgrade: rc=%d\n", rc);
-
- // Do not fail even if upgrade failed - machine is bootable
- // Note that if this code is ever hit, there is a *serious* problem
- // since KDFs should never fail. You *must* fix the kdf before
- // proceeding!
- if (rc) {
- SLOGW(
- "Upgrade failed with error %d,"
- " but continuing with previous state",
- rc);
- rc = 0;
- }
- }
- }
-
-errout:
- if (intermediate_key) {
- memset(intermediate_key, 0, intermediate_key_size);
- free(intermediate_key);
- }
- return rc;
-}
-
-/*
- * Called by vold when it's asked to mount an encrypted external
- * storage volume. The incoming partition has no crypto header/footer,
- * as any metadata is been stored in a separate, small partition. We
- * assume it must be using our same crypt type and keysize.
- */
-int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const KeyBuffer& key,
- std::string* out_crypto_blkdev) {
- auto crypto_type = get_crypto_type();
- if (key.size() != crypto_type.get_keysize()) {
- SLOGE("Raw keysize %zu does not match crypt keysize %zu", key.size(),
- crypto_type.get_keysize());
- return -1;
- }
- uint64_t nr_sec = 0;
- if (::GetBlockDev512Sectors(real_blkdev, &nr_sec) != android::OK) {
- SLOGE("Failed to get size of %s: %s", real_blkdev, strerror(errno));
- return -1;
- }
-
- struct crypt_mnt_ftr ext_crypt_ftr;
- memset(&ext_crypt_ftr, 0, sizeof(ext_crypt_ftr));
- ext_crypt_ftr.fs_size = nr_sec;
- ext_crypt_ftr.keysize = crypto_type.get_keysize();
- strlcpy((char*)ext_crypt_ftr.crypto_type_name, crypto_type.get_kernel_name(),
- MAX_CRYPTO_TYPE_NAME_LEN);
- uint32_t flags = 0;
- if (fscrypt_is_native() &&
- android::base::GetBoolProperty("ro.crypto.allow_encrypt_override", false))
- flags |= CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE;
-
- return create_crypto_blk_dev(&ext_crypt_ftr, reinterpret_cast<const unsigned char*>(key.data()),
- real_blkdev, out_crypto_blkdev, label, flags);
-}
-
-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];
- property_get("ro.crypto.state", encrypted_state, "");
- if (master_key_saved || strcmp(encrypted_state, "encrypted")) {
- SLOGE(
- "encrypted fs already validated or not running with encryption,"
- " aborting");
- return -1;
- }
-
- if (get_crypt_ftr_and_key(crypt_ftr)) {
- SLOGE("Error getting crypt footer and key");
- return -1;
- }
-
- return 0;
-}
-
-int cryptfs_check_passwd(const char* passwd) {
- SLOGI("cryptfs_check_passwd");
- if (fscrypt_is_native()) {
- SLOGE("cryptfs_check_passwd not valid for file encryption");
- return -1;
- }
-
- struct crypt_mnt_ftr crypt_ftr;
- int rc;
-
- rc = check_unmounted_and_get_ftr(&crypt_ftr);
- if (rc) {
- SLOGE("Could not get footer");
- return rc;
- }
-
- rc = test_mount_encrypted_fs(&crypt_ftr, passwd, DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
- if (rc) {
- SLOGE("Password did not match");
- return rc;
- }
-
- if (crypt_ftr.flags & CRYPT_FORCE_COMPLETE) {
- // Here we have a default actual password but a real password
- // we must test against the scrypted value
- // First, we must delete the crypto block device that
- // test_mount_encrypted_fs leaves behind as a side effect
- delete_crypto_blk_dev(CRYPTO_BLOCK_DEVICE);
- rc = test_mount_encrypted_fs(&crypt_ftr, DEFAULT_PASSWORD, DATA_MNT_POINT,
- CRYPTO_BLOCK_DEVICE);
- if (rc) {
- SLOGE("Default password did not match on reboot encryption");
- return rc;
- }
-
- crypt_ftr.flags &= ~CRYPT_FORCE_COMPLETE;
- put_crypt_ftr_and_key(&crypt_ftr);
- rc = cryptfs_changepw(crypt_ftr.crypt_type, passwd);
- if (rc) {
- SLOGE("Could not change password on reboot encryption");
- return rc;
- }
- }
-
- if (crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) {
- cryptfs_clear_password();
- password = strdup(passwd);
- struct timespec now;
- clock_gettime(CLOCK_BOOTTIME, &now);
- password_expiry_time = now.tv_sec + password_max_age_seconds;
- }
-
- return rc;
-}
-
-int cryptfs_verify_passwd(const char* passwd) {
- struct crypt_mnt_ftr crypt_ftr;
- unsigned char decrypted_master_key[MAX_KEY_LEN];
- char encrypted_state[PROPERTY_VALUE_MAX];
- int rc;
-
- property_get("ro.crypto.state", encrypted_state, "");
- if (strcmp(encrypted_state, "encrypted")) {
- SLOGE("device not encrypted, aborting");
- return -2;
- }
-
- if (!master_key_saved) {
- SLOGE("encrypted fs not yet mounted, aborting");
- return -1;
- }
-
- if (!saved_mount_point) {
- SLOGE("encrypted fs failed to save mount point, aborting");
- return -1;
- }
-
- if (get_crypt_ftr_and_key(&crypt_ftr)) {
- SLOGE("Error getting crypt footer and key\n");
- return -1;
- }
-
- if (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) {
- /* If the device has no password, then just say the password is valid */
- rc = 0;
- } else {
- decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
- 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 get_crypto_type().get_keysize() 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 int 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 = get_crypto_type().get_keysize();
-
- switch (keymaster_check_compatibility()) {
- case 1:
- ftr->kdf_type = KDF_SCRYPT_KEYMASTER;
- break;
-
- case 0:
- ftr->kdf_type = KDF_SCRYPT;
- break;
-
- default:
- SLOGE("keymaster_check_compatibility failed");
- return -1;
- }
-
- 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;
- }
-
- return 0;
-}
-
-#define FRAMEWORK_BOOT_WAIT 60
-
-static int cryptfs_SHA256_fileblock(const char* filename, __le8* buf) {
- int fd = open(filename, O_RDONLY | O_CLOEXEC);
- if (fd == -1) {
- SLOGE("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) {
- SLOGE("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 cryptfs_enable_all_volumes(struct crypt_mnt_ftr* crypt_ftr, const char* crypto_blkdev,
- const char* real_blkdev, int previously_encrypted_upto) {
- off64_t cur_encryption_done = 0, tot_encryption_size = 0;
- int rc = -1;
-
- /* The size of the userdata partition, and add in the vold volumes below */
- tot_encryption_size = crypt_ftr->fs_size;
-
- rc = cryptfs_enable_inplace(crypto_blkdev, real_blkdev, crypt_ftr->fs_size, &cur_encryption_done,
- tot_encryption_size, previously_encrypted_upto, true);
-
- if (rc == ENABLE_INPLACE_ERR_DEV) {
- /* Hack for b/17898962 */
- SLOGE("cryptfs_enable: crypto block dev failure. Must reboot...\n");
- cryptfs_reboot(RebootType::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");
- }
-
- return rc;
-}
-
-// static int vold_unmountAll(void) {
-// VolumeManager* vm = VolumeManager::Instance();
-// return vm->unmountAll();
-// }
-
-int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
- std::string crypto_blkdev;
- std::string real_blkdev;
- unsigned char decrypted_master_key[MAX_KEY_LEN];
- int rc = -1, i;
- struct crypt_mnt_ftr crypt_ftr;
- struct crypt_persist_data* pdata;
- char encrypted_state[PROPERTY_VALUE_MAX];
- char lockid[32] = {0};
- std::string key_loc;
- int num_vols;
- off64_t previously_encrypted_upto = 0;
- bool rebootEncryption = false;
- bool onlyCreateHeader = false;
- // std::unique_ptr<android::wakelock::WakeLock> wakeLock = nullptr;
-
- if (get_crypt_ftr_and_key(&crypt_ftr) == 0) {
- if (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS) {
- /* An encryption was underway and was interrupted */
- 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);
- } else if (crypt_ftr.flags & CRYPT_FORCE_ENCRYPTION) {
- if (!check_ftr_sha(&crypt_ftr)) {
- memset(&crypt_ftr, 0, sizeof(crypt_ftr));
- put_crypt_ftr_and_key(&crypt_ftr);
- goto error_unencrypted;
- }
-
- /* Doing a reboot-encryption*/
- crypt_ftr.flags &= ~CRYPT_FORCE_ENCRYPTION;
- crypt_ftr.flags |= CRYPT_FORCE_COMPLETE;
- rebootEncryption = true;
- }
- } else {
- // We don't want to accidentally reference invalid data.
- memset(&crypt_ftr, 0, sizeof(crypt_ftr));
- }
-
- property_get("ro.crypto.state", encrypted_state, "");
- if (!strcmp(encrypted_state, "encrypted") && !previously_encrypted_upto) {
- SLOGE("Device is already running encrypted, aborting");
- goto error_unencrypted;
- }
-
- get_crypt_info(&key_loc, &real_blkdev);
-
- /* Get the size of the real block device */
- uint64_t nr_sec;
- if (::GetBlockDev512Sectors(real_blkdev, &nr_sec) != android::OK) {
- SLOGE("Cannot get size of block device %s\n", real_blkdev.c_str());
- goto error_unencrypted;
- }
-
- /* If doing inplace encryption, make sure the orig fs doesn't include the crypto footer */
- if (key_loc == KEY_IN_FOOTER) {
- uint64_t fs_size_sec, max_fs_size_sec;
- fs_size_sec = get_fs_size(real_blkdev.c_str());
- if (fs_size_sec == 0) fs_size_sec = get_f2fs_filesystem_size_sec(real_blkdev.data());
-
- max_fs_size_sec = nr_sec - (CRYPT_FOOTER_OFFSET / CRYPT_SECTOR_SIZE);
-
- if (fs_size_sec > max_fs_size_sec) {
- SLOGE("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());
- // wakeLock = std::make_unique<android::wakelock::WakeLock>(lockid);
-
- /* 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");
- SLOGD("Just asked init to shut down class main\n");
-
- /* Ask vold to unmount all devices that it manages */
- // if (vold_unmountAll()) {
- // SLOGE("Failed to unmount all vold managed devices");
- // }
-
- /* no_ui means we are being called from init, not settings.
- Now we always reboot from settings, so !no_ui means reboot
- */
- if (!no_ui) {
- /* Try fallback, which is to reboot and try there */
- onlyCreateHeader = true;
- FILE* breadcrumb = fopen(BREADCRUMB_FILE, "we");
- if (breadcrumb == 0) {
- SLOGE("Failed to create breadcrumb file");
- goto error_shutting_down;
- }
- fclose(breadcrumb);
- }
-
- /* Do extra work for a better UX when doing the long inplace encryption */
- if (!onlyCreateHeader) {
- /* 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.
- */
- wait_and_unmount(DATA_MNT_POINT, true);
- 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 */
- prep_data_fs();
-
- /* 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);
- }
-
- /* Start the actual work of making an encrypted filesystem */
- /* Initialize a crypt_mnt_ftr for the partition */
- if (previously_encrypted_upto == 0 && !rebootEncryption) {
- if (cryptfs_init_crypt_mnt_ftr(&crypt_ftr)) {
- goto error_shutting_down;
- }
-
- if (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 */
- if (onlyCreateHeader) {
- crypt_ftr.flags |= CRYPT_FORCE_ENCRYPTION;
- } else {
- crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE;
- }
- crypt_ftr.crypt_type = crypt_type;
- strlcpy((char*)crypt_ftr.crypto_type_name, get_crypto_type().get_kernel_name(),
- MAX_CRYPTO_TYPE_NAME_LEN);
-
- /* Make an encrypted master key */
- if (create_encrypted_random_key(onlyCreateHeader ? DEFAULT_PASSWORD : passwd,
- crypt_ftr.master_key, crypt_ftr.salt, &crypt_ftr)) {
- SLOGE("Cannot create encrypted master key\n");
- goto error_shutting_down;
- }
-
- /* Replace scrypted intermediate key if we are preparing for a reboot */
- if (onlyCreateHeader) {
- unsigned char fake_master_key[MAX_KEY_LEN];
- unsigned char encrypted_fake_master_key[MAX_KEY_LEN];
- memset(fake_master_key, 0, sizeof(fake_master_key));
- encrypt_master_key(passwd, crypt_ftr.salt, fake_master_key, encrypted_fake_master_key,
- &crypt_ftr);
- }
-
- /* 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 = (crypt_persist_data*)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();
- }
- }
-
- if (onlyCreateHeader) {
- sleep(2);
- cryptfs_reboot(RebootType::reboot);
- }
-
- if (!no_ui || rebootEncryption) {
- /* startup service classes main and late_start */
- property_set("vold.decrypt", "trigger_restart_min_framework");
- SLOGD("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.
- */
- }
-
- decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
- ALOGE("cryptfs_enable_internal\n");
- create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev.c_str(), &crypto_blkdev,
- CRYPTO_BLOCK_DEVICE, 0);
-
- /* 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.c_str(), hash_first_block);
-
- if (!rc &&
- memcmp(hash_first_block, crypt_ftr.hash_first_block, sizeof(hash_first_block)) != 0) {
- SLOGE("Checksums do not match - trigger wipe");
- rc = -1;
- }
- }
-
- if (!rc) {
- rc = cryptfs_enable_all_volumes(&crypt_ftr, crypto_blkdev.c_str(), real_blkdev.data(),
- 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.c_str(), crypt_ftr.hash_first_block);
- if (rc) {
- SLOGE("Error calculating checksum for continuing encryption");
- rc = -1;
- }
- }
-
- /* Undo the dm-crypt mapping whether we succeed or not */
- delete_crypto_blk_dev(CRYPTO_BLOCK_DEVICE);
-
- if (!rc) {
- /* Success */
- crypt_ftr.flags &= ~CRYPT_INCONSISTENT_STATE;
-
- if (crypt_ftr.encrypted_upto != crypt_ftr.fs_size) {
- SLOGD("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");
- property_set("ro.crypto.type", "block");
- // wakeLock.reset(nullptr);
- if (rebootEncryption && crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) {
- // Bring up cryptkeeper that will check the password and set it
- property_set("vold.decrypt", "trigger_shutdown_framework");
- sleep(2);
- property_set("vold.encrypt_progress", "");
- cryptfs_trigger_restart_min_framework();
- } else {
- 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(RebootType::reboot);
- }
- } else {
- sleep(2); /* Partially encrypted, ensure writes flushed to ssd */
- cryptfs_reboot(RebootType::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 */
- SLOGE("encryption failed - rebooting into recovery to wipe data\n");
- std::string err;
- const std::vector<std::string> options = {
- "--wipe_data\n--reason=cryptfs_enable_internal\n"};
- if (!write_bootloader_message(options, &err)) {
- SLOGE("could not write bootloader message: %s", err.c_str());
- }
- cryptfs_reboot(RebootType::recovery);
- } else {
- /* set property to trigger dialog */
- property_set("vold.encrypt_progress", "error_partially_encrypted");
- }
- 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");
- return rc;
-
-error_unencrypted:
- property_set("vold.encrypt_progress", "error_not_encrypted");
- 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.
- */
- SLOGE(
- "Error enabling encryption after framework is shutdown, no data changed, restarting "
- "system");
- cryptfs_reboot(RebootType::reboot);
-
- /* shouldn't get here */
- property_set("vold.encrypt_progress", "error_shutting_down");
- return -1;
-}
-
-int cryptfs_enable(int type, const char* passwd, int no_ui) {
- return cryptfs_enable_internal(type, passwd, no_ui);
-}
-
-int cryptfs_enable_default(int no_ui) {
- return cryptfs_enable_internal(CRYPT_TYPE_DEFAULT, DEFAULT_PASSWORD, no_ui);
-}
-
-int cryptfs_changepw(int crypt_type, const char* newpw) {
- if (fscrypt_is_native()) {
- SLOGE("cryptfs_changepw not valid for file encryption");
- return -1;
- }
-
- struct crypt_mnt_ftr crypt_ftr;
- int rc;
-
- /* This is only allowed after we've successfully decrypted the master key */
- if (!master_key_saved) {
- SLOGE("Key not saved, aborting");
- return -1;
- }
-
- if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) {
- SLOGE("Invalid crypt_type %d", crypt_type);
- return -1;
- }
-
- /* get key */
- if (get_crypt_ftr_and_key(&crypt_ftr)) {
- SLOGE("Error getting crypt footer and key");
- return -1;
- }
-
- crypt_ftr.crypt_type = crypt_type;
-
- rc = encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD : newpw,
- crypt_ftr.salt, saved_master_key, crypt_ftr.master_key, &crypt_ftr);
- if (rc) {
- SLOGE("Encrypt master key failed: %d", rc);
- return -1;
- }
- /* save the key */
- put_crypt_ftr_and_key(&crypt_ftr);
-
- return 0;
-}
-
-static unsigned int persist_get_max_entries(int encrypted) {
- struct crypt_mnt_ftr crypt_ftr;
- unsigned int dsize;
-
- /* 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)) {
- /* Something is wrong, assume no space for entries */
- return 0;
- }
- dsize = crypt_ftr.persist_data_size;
- } else {
- dsize = CRYPT_PERSIST_DATA_SIZE;
- }
-
- if (dsize > sizeof(struct crypt_persist_data)) {
- return (dsize - sizeof(struct crypt_persist_data)) / sizeof(struct crypt_persist_entry);
- } else {
- return 0;
- }
-}
-
-static int persist_get_key(const 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(const char* fieldname, const char* value, int encrypted) {
- unsigned int i;
- unsigned int num;
- unsigned int max_persistent_entries;
-
- if (persist_data == NULL) {
- return -1;
- }
-
- max_persistent_entries = persist_get_max_entries(encrypted);
-
- 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;
-}
-
-/**
- * Test if key is part of the multi-entry (field, index) sequence. Return non-zero if key is in the
- * sequence and its index is greater than or equal to index. Return 0 otherwise.
- */
-int match_multi_entry(const char* key, const char* field, unsigned index) {
- std::string key_ = key;
- std::string field_ = field;
-
- std::string parsed_field;
- unsigned parsed_index;
-
- std::string::size_type split = key_.find_last_of('_');
- if (split == std::string::npos) {
- parsed_field = key_;
- parsed_index = 0;
- } else {
- parsed_field = key_.substr(0, split);
- parsed_index = std::stoi(key_.substr(split + 1));
- }
-
- return parsed_field == field_ && parsed_index >= index;
-}
-
-/*
- * Delete entry/entries from persist_data. If the entries are part of a multi-segment field, all
- * remaining entries starting from index will be deleted.
- * returns PERSIST_DEL_KEY_OK if deletion succeeds,
- * PERSIST_DEL_KEY_ERROR_NO_FIELD if the field does not exist,
- * and PERSIST_DEL_KEY_ERROR_OTHER if error occurs.
- *
- */
-static int persist_del_keys(const char* fieldname, unsigned index) {
- unsigned int i;
- unsigned int j;
- unsigned int num;
-
- if (persist_data == NULL) {
- return PERSIST_DEL_KEY_ERROR_OTHER;
- }
-
- num = persist_data->persist_valid_entries;
-
- j = 0; // points to the end of non-deleted entries.
- // Filter out to-be-deleted entries in place.
- for (i = 0; i < num; i++) {
- if (!match_multi_entry(persist_data->persist_entry[i].key, fieldname, index)) {
- persist_data->persist_entry[j] = persist_data->persist_entry[i];
- j++;
- }
- }
-
- if (j < num) {
- persist_data->persist_valid_entries = j;
- // Zeroise the remaining entries
- memset(&persist_data->persist_entry[j], 0, (num - j) * sizeof(struct crypt_persist_entry));
- return PERSIST_DEL_KEY_OK;
- } else {
- // Did not find an entry matching the given fieldname
- return PERSIST_DEL_KEY_ERROR_NO_FIELD;
- }
-}
-
-static int persist_count_keys(const char* fieldname) {
- unsigned int i;
- unsigned int count;
-
- if (persist_data == NULL) {
- return -1;
- }
-
- count = 0;
- for (i = 0; i < persist_data->persist_valid_entries; i++) {
- if (match_multi_entry(persist_data->persist_entry[i].key, fieldname, 0)) {
- count++;
- }
- }
-
- return count;
-}
-
-/* Return the value of the specified field. */
-int cryptfs_getfield(const char* fieldname, char* value, int len) {
- if (fscrypt_is_native()) {
- SLOGE("Cannot get field when file encrypted");
- return -1;
- }
-
- char temp_value[PROPERTY_VALUE_MAX];
- /* CRYPTO_GETFIELD_OK is success,
- * CRYPTO_GETFIELD_ERROR_NO_FIELD is value not set,
- * CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL is buffer (as given by len) too small,
- * CRYPTO_GETFIELD_ERROR_OTHER is any other error
- */
- int rc = CRYPTO_GETFIELD_ERROR_OTHER;
- int i;
- char temp_field[PROPERTY_KEY_MAX];
-
- if (persist_data == NULL) {
- load_persistent_data();
- if (persist_data == NULL) {
- SLOGE("Getfield error, cannot load persistent data");
- goto out;
- }
- }
-
- // Read value from persistent entries. If the original value is split into multiple entries,
- // stitch them back together.
- if (!persist_get_key(fieldname, temp_value)) {
- // We found it, copy it to the caller's buffer and keep going until all entries are read.
- if (strlcpy(value, temp_value, len) >= (unsigned)len) {
- // value too small
- rc = CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
- goto out;
- }
- rc = CRYPTO_GETFIELD_OK;
-
- for (i = 1; /* break explicitly */; i++) {
- if (snprintf(temp_field, sizeof(temp_field), "%s_%d", fieldname, i) >=
- (int)sizeof(temp_field)) {
- // If the fieldname is very long, we stop as soon as it begins to overflow the
- // maximum field length. At this point we have in fact fully read out the original
- // value because cryptfs_setfield would not allow fields with longer names to be
- // written in the first place.
- break;
- }
- if (!persist_get_key(temp_field, temp_value)) {
- if (strlcat(value, temp_value, len) >= (unsigned)len) {
- // value too small.
- rc = CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
- goto out;
- }
- } else {
- // Exhaust all entries.
- break;
- }
- }
- } else {
- /* Sadness, it's not there. Return the error */
- rc = CRYPTO_GETFIELD_ERROR_NO_FIELD;
- }
-
-out:
- return rc;
-}
-
-/* Set the value of the specified field. */
-int cryptfs_setfield(const char* fieldname, const char* value) {
- if (fscrypt_is_native()) {
- SLOGE("Cannot set field when file encrypted");
- return -1;
- }
-
- char encrypted_state[PROPERTY_VALUE_MAX];
- /* 0 is success, negative values are error */
- int rc = CRYPTO_SETFIELD_ERROR_OTHER;
- int encrypted = 0;
- unsigned int field_id;
- char temp_field[PROPERTY_KEY_MAX];
- unsigned int num_entries;
- unsigned int max_keylen;
-
- if (persist_data == NULL) {
- load_persistent_data();
- if (persist_data == NULL) {
- SLOGE("Setfield error, cannot load persistent data");
- goto out;
- }
- }
-
- property_get("ro.crypto.state", encrypted_state, "");
- if (!strcmp(encrypted_state, "encrypted")) {
- encrypted = 1;
- }
-
- // Compute the number of entries required to store value, each entry can store up to
- // (PROPERTY_VALUE_MAX - 1) chars
- if (strlen(value) == 0) {
- // Empty value also needs one entry to store.
- num_entries = 1;
- } else {
- num_entries = (strlen(value) + (PROPERTY_VALUE_MAX - 1) - 1) / (PROPERTY_VALUE_MAX - 1);
- }
-
- max_keylen = strlen(fieldname);
- if (num_entries > 1) {
- // Need an extra "_%d" suffix.
- max_keylen += 1 + log10(num_entries);
- }
- if (max_keylen > PROPERTY_KEY_MAX - 1) {
- rc = CRYPTO_SETFIELD_ERROR_FIELD_TOO_LONG;
- goto out;
- }
-
- // Make sure we have enough space to write the new value
- if (persist_data->persist_valid_entries + num_entries - persist_count_keys(fieldname) >
- persist_get_max_entries(encrypted)) {
- rc = CRYPTO_SETFIELD_ERROR_VALUE_TOO_LONG;
- goto out;
- }
-
- // Now that we know persist_data has enough space for value, let's delete the old field first
- // to make up space.
- persist_del_keys(fieldname, 0);
-
- if (persist_set_key(fieldname, value, encrypted)) {
- // fail to set key, should not happen as we have already checked the available space
- SLOGE("persist_set_key() error during setfield()");
- goto out;
- }
-
- for (field_id = 1; field_id < num_entries; field_id++) {
- snprintf(temp_field, sizeof(temp_field), "%s_%u", fieldname, field_id);
-
- if (persist_set_key(temp_field, value + field_id * (PROPERTY_VALUE_MAX - 1), encrypted)) {
- // fail to set key, should not happen as we have already checked the available space.
- SLOGE("persist_set_key() error during setfield()");
- goto out;
- }
- }
-
- /* If we are running encrypted, save the persistent data now */
- if (encrypted) {
- if (save_persistent_data()) {
- SLOGE("Setfield error, cannot save persistent data");
- goto out;
- }
- }
-
- rc = CRYPTO_SETFIELD_OK;
-
-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) {
- int crypt_type = cryptfs_get_password_type();
- if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) {
- SLOGE("Bad crypt type - error");
- } else if (crypt_type != CRYPT_TYPE_DEFAULT) {
- SLOGD(
- "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) {
- SLOGD("Password is default - restarting filesystem");
- cryptfs_restart_internal(0);
- return 0;
- } else {
- SLOGE("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) {
- if (fscrypt_is_native()) {
- SLOGE("cryptfs_get_password_type not valid for file encryption");
- return -1;
- }
-
- struct crypt_mnt_ftr crypt_ftr;
-
- if (get_crypt_ftr_and_key(&crypt_ftr)) {
- SLOGE("Error getting crypt footer and key\n");
- return -1;
- }
-
- if (crypt_ftr.flags & CRYPT_INCONSISTENT_STATE) {
- return -1;
- }
-
- return crypt_ftr.crypt_type;
-}
-
-const char* cryptfs_get_password() {
- if (fscrypt_is_native()) {
- SLOGE("cryptfs_get_password not valid for file encryption");
- return 0;
- }
-
- struct timespec now;
- clock_gettime(CLOCK_BOOTTIME, &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;
- }
-}
-
-int cryptfs_isConvertibleToFBE() {
- auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
- return entry && entry->fs_mgr_flags.force_fde_or_fbe;
-}
diff --git a/crypto/fscrypt/cryptfs.h b/crypto/fscrypt/cryptfs.h
deleted file mode 100644
index 728b775..0000000
--- a/crypto/fscrypt/cryptfs.h
+++ /dev/null
@@ -1,79 +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.
- */
-
-#ifndef ANDROID_VOLD_CRYPTFS_H
-#define ANDROID_VOLD_CRYPTFS_H
-
-#include <string>
-
-#include <linux/types.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-#include <cutils/properties.h>
-
-#include "KeyBuffer.h"
-#include "KeyUtil.h"
-
-#define CRYPT_FOOTER_OFFSET 0x4000
-
-/* Return values for cryptfs_crypto_complete */
-#define CRYPTO_COMPLETE_NOT_ENCRYPTED 1
-#define CRYPTO_COMPLETE_ENCRYPTED 0
-#define CRYPTO_COMPLETE_BAD_METADATA (-1)
-#define CRYPTO_COMPLETE_PARTIAL (-2)
-#define CRYPTO_COMPLETE_INCONSISTENT (-3)
-#define CRYPTO_COMPLETE_CORRUPT (-4)
-
-/* Return values for cryptfs_getfield */
-#define CRYPTO_GETFIELD_OK 0
-#define CRYPTO_GETFIELD_ERROR_NO_FIELD (-1)
-#define CRYPTO_GETFIELD_ERROR_OTHER (-2)
-#define CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL (-3)
-
-/* Return values for cryptfs_setfield */
-#define CRYPTO_SETFIELD_OK 0
-#define CRYPTO_SETFIELD_ERROR_OTHER (-1)
-#define CRYPTO_SETFIELD_ERROR_FIELD_TOO_LONG (-2)
-#define CRYPTO_SETFIELD_ERROR_VALUE_TOO_LONG (-3)
-
-/* Return values for persist_del_key */
-#define PERSIST_DEL_KEY_OK 0
-#define PERSIST_DEL_KEY_ERROR_OTHER (-1)
-#define PERSIST_DEL_KEY_ERROR_NO_FIELD (-2)
-
-// Exposed for testing only
-int match_multi_entry(const char* key, const char* field, unsigned index);
-
-int cryptfs_crypto_complete(void);
-int cryptfs_check_passwd(const char* pw);
-int cryptfs_verify_passwd(const char* pw);
-int cryptfs_restart(void);
-int cryptfs_enable(int type, const char* passwd, int no_ui);
-int cryptfs_changepw(int type, const char* newpw);
-int cryptfs_enable_default(int no_ui);
-int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev,
- const ::KeyBuffer& key, std::string* out_crypto_blkdev);
-int cryptfs_getfield(const char* fieldname, char* value, int len);
-int cryptfs_setfield(const char* fieldname, const char* value);
-int cryptfs_mount_default_encrypted(void);
-int cryptfs_get_password_type(void);
-const char* cryptfs_get_password(void);
-void cryptfs_clear_password(void);
-int cryptfs_isConvertibleToFBE(void);
-const KeyGeneration cryptfs_get_keygen();
-
-#endif /* ANDROID_VOLD_CRYPTFS_H */
diff --git a/crypto/fscrypt/fscrypt-common.h b/crypto/fscrypt/fscrypt-common.h
deleted file mode 100755
index e5733c6..0000000
--- a/crypto/fscrypt/fscrypt-common.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <map>
-// Store main DE/CE policy
-extern std::map<userid_t, EncryptionPolicy> s_de_policies;
-extern std::map<userid_t, EncryptionPolicy> s_ce_policies;
-extern std::string de_key_raw_ref;
\ No newline at end of file
diff --git a/crypto/fscrypt/fscrypt_policy.cpp b/crypto/fscrypt/fscrypt_policy.cpp
deleted file mode 100755
index c4986e5..0000000
--- a/crypto/fscrypt/fscrypt_policy.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2015 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 <array>
-
-#include <asm/ioctl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/fs.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <cutils/properties.h>
-#include <logwrap/logwrap.h>
-#include <utils/misc.h>
-#include <fscrypt/fscrypt.h>
-#include "KeyUtil.h"
-
-#include "fscrypt_policy.h"
-
-static int encryption_mode = FS_ENCRYPTION_MODE_PRIVATE;
-
-bool fscrypt_is_native() {
- LOG(ERROR) << "fscrypt_is_native::ro.crypto.type";
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.crypto.type", value, "none");
- return !strcmp(value, "file");
-}
-
-extern "C" void bytes_to_hex(const uint8_t *bytes, size_t num_bytes, char *hex) {
- for (size_t i = 0; i < num_bytes; i++) {
- sprintf(&hex[2 * i], "%02x", bytes[i]);
- }
-}
-
-static bool is_dir_empty(const char *dirname, bool *is_empty)
-{
- int n = 0;
- auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(dirname), closedir);
- if (!dirp) {
- PLOG(ERROR) << "Unable to read directory: " << dirname;
- return false;
- }
- for (;;) {
- errno = 0;
- auto entry = readdir(dirp.get());
- if (!entry) {
- if (errno) {
- PLOG(ERROR) << "Unable to read directory: " << dirname;
- return false;
- }
- break;
- }
- if (strcmp(entry->d_name, "lost+found") != 0) { // Skip lost+found
- ++n;
- if (n > 2) {
- *is_empty = false;
- return true;
- }
- }
- }
- *is_empty = true;
- return true;
-}
-
-static uint8_t fscrypt_get_policy_flags(int filenames_encryption_mode) {
- if (filenames_encryption_mode == FS_ENCRYPTION_MODE_AES_256_CTS) {
- // Use legacy padding with our original filenames encryption mode.
- return FS_POLICY_FLAGS_PAD_4;
- } else if (filenames_encryption_mode == FS_ENCRYPTION_MODE_ADIANTUM) {
- // Use DIRECT_KEY for Adiantum, since it's much more efficient but just
- // as secure since Android doesn't reuse the same master key for
- // multiple encryption modes
- return (FS_POLICY_FLAGS_PAD_16 | FS_POLICY_FLAG_DIRECT_KEY);
- }
- // With a new mode we can use the better padding flag without breaking existing devices: pad
- // filenames with zeroes to the next 16-byte boundary. This is more secure (helps hide the
- // length of filenames) and makes the inputs evenly divisible into blocks which is more
- // efficient for encryption and decryption.
- return FS_POLICY_FLAGS_PAD_16;
-}
-
-extern "C" bool fscrypt_set_mode() {
- const char* mode_file = "/data/unencrypted/mode";
- struct stat st;
- if (stat(mode_file, &st) != 0 || st.st_size <= 0) {
- printf("Invalid encryption mode file %s\n", mode_file);
- return false;
- }
- size_t mode_size = st.st_size;
- char contents_encryption_mode[mode_size + 1];
- memset((void*)contents_encryption_mode, 0, mode_size + 1);
- int fd = open(mode_file, O_RDONLY);
- if (fd < 0) {
- printf("error opening '%s': %s\n", mode_file, strerror(errno));
- return false;
- }
- if (read(fd, contents_encryption_mode, mode_size) != mode_size) {
- printf("read error on '%s': %s\n", mode_file, strerror(errno));
- close(fd);
- return false;
- }
- close(fd);
-
- std::string contents_encryption_mode_string = std::string(contents_encryption_mode);
- int pos = contents_encryption_mode_string.find(":");
- LOG(INFO) << "contents_encryption_mode_string: " << contents_encryption_mode_string.substr(0, pos);
-
- if (contents_encryption_mode_string.substr(0, pos) == "software") {
- encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
- } else if (contents_encryption_mode_string.substr(0, pos) == "ice") {
- encryption_mode = FS_ENCRYPTION_MODE_PRIVATE;
- } else {
- printf("Invalid encryption mode '%s'\n", contents_encryption_mode);
- return false;
- }
-
- printf("set encryption mode to %i\n", encryption_mode);
- return true;
-}
-
-#ifdef USE_FSCRYPT_POLICY_V1
-extern "C" bool fscrypt_policy_set_struct(const char *directory, const struct fscrypt_policy_v1 *fep) {
-#else
-extern "C" bool fscrypt_policy_set_struct(const char *directory, const struct fscrypt_policy_v2 *fep) {
-#endif
- int fd = open(directory, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
- if (fd == -1) {
- printf("failed to open %s\n", directory);
- PLOG(ERROR) << "Failed to open directory " << directory;
- return false;
- }
- if (isFsKeyringSupported()) {
- if (ioctl(fd, FS_IOC_SET_ENCRYPTION_POLICY, fep)) {
- PLOG(ERROR) << "Failed to set encryption policy for " << directory;
- close(fd);
- return false;
- }
- } else {
- if (ioctl(fd, FS_IOC_SET_ENCRYPTION_POLICY, fep)) {
- PLOG(ERROR) << "Failed to set encryption policy for " << directory;
- close(fd);
- return false;
- }
- }
- close(fd);
- return true;
-}
-
-#ifdef USE_FSCRYPT_POLICY_V1
-extern "C" bool fscrypt_policy_get_struct(const char *directory, struct fscrypt_policy_v1 *fep) {
-#else
-extern "C" bool fscrypt_policy_get_struct(const char *directory, struct fscrypt_policy_v2 *fep) {
-#endif
- int fd = open(directory, O_DIRECTORY | O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
- if (fd == -1) {
- PLOG(ERROR) << "Failed to open directory " << directory;
- return false;
- }
-#ifdef USE_FSCRYPT_POLICY_V1
- memset(fep, 0, sizeof(fscrypt_policy_v1));
-#else
- memset(fep, 0, sizeof(fscrypt_policy_v2));
-#endif
- struct fscrypt_get_policy_ex_arg ex_policy = {0};
-
- if (isFsKeyringSupported()) {
- ex_policy.policy_size = sizeof(ex_policy.policy);
- if (ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY_EX, &ex_policy) != 0) {
- PLOG(ERROR) << "Failed to get encryption policy for " << directory;
- close(fd);
- return false;
- }
-#ifdef USE_FSCRYPT_POLICY_V1
- memcpy(fep, &ex_policy.policy.v1, sizeof(ex_policy.policy.v1));
-#else
- memcpy(fep, &ex_policy.policy.v2, sizeof(ex_policy.policy.v2));
-#endif
- } else {
- if (ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &ex_policy.policy.v1) != 0) {
- PLOG(ERROR) << "Failed to get encryption policy for " << directory;
- close(fd);
- return false;
- }
- memcpy(fep, &ex_policy.policy.v1, sizeof(ex_policy.policy.v1));
- }
- close(fd);
- return true;
-}
diff --git a/crypto/fscrypt/fscrypt_policy.h b/crypto/fscrypt/fscrypt_policy.h
deleted file mode 100755
index 5714790..0000000
--- a/crypto/fscrypt/fscrypt_policy.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2016 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 _FS_CRYPT_H_
-#define _FS_CRYPT_H_
-
-#include <sys/cdefs.h>
-#include <stdbool.h>
-#include <cutils/multiuser.h>
-#include <linux/fs.h>
-
-__BEGIN_DECLS
-
-#define FS_KEY_DESCRIPTOR_SIZE_HEX (2 * FS_KEY_DESCRIPTOR_SIZE + 1)
-#define FSCRYPT_KEY_IDENTIFIER_HEX_SIZE ((2 * FSCRYPT_KEY_IDENTIFIER_SIZE) + 1)
-
-#ifdef USE_FSCRYPT_POLICY_V1
-#define USER_CE_FSCRYPT_POLICY "0CE"
-#define USER_DE_FSCRYPT_POLICY "0DE"
-#define SYSTEM_DE_FSCRYPT_POLICY "0DK"
-#else
-#define USER_CE_FSCRYPT_POLICY "2CE"
-#define USER_DE_FSCRYPT_POLICY "2DE"
-#define SYSTEM_DE_FSCRYPT_POLICY "2DK"
-#endif
-
-#define FSCRYPT_V1 "0"
-#define FSCRYPT_V2 "2"
-#define SYSTEM_DE_KEY "DK"
-#define USER_CE_KEY "C"
-#define USER_DE_KEY "D"
-
-/* modes not supported by upstream kernel, so not in <linux/fs.h> */
-#define FS_ENCRYPTION_MODE_AES_256_HEH 126
-#define FS_ENCRYPTION_MODE_PRIVATE 127
-
-/* new definition, not yet in Bionic's <linux/fs.h> */
-#ifndef FS_ENCRYPTION_MODE_ADIANTUM
-#define FS_ENCRYPTION_MODE_ADIANTUM 9
-#endif
-
-/* new definition, not yet in Bionic's <linux/fs.h> */
-#ifndef FS_POLICY_FLAG_DIRECT_KEY
-#define FS_POLICY_FLAG_DIRECT_KEY 0x4
-#endif
-
-#define HEX_LOOKUP "0123456789abcdef"
-
-bool fscrypt_set_mode();
-
-#ifdef USE_FSCRYPT_POLICY_V1
-bool lookup_ref_key(struct fscrypt_policy_v1 *fep, uint8_t* policy_type);
-#else
-bool lookup_ref_key(struct fscrypt_policy_v2 *fep, uint8_t* policy_type);
-#endif
-
-bool lookup_ref_tar(const uint8_t *policy_type, uint8_t *policy);
-
-#ifdef USE_FSCRYPT_POLICY_V1
-bool fscrypt_policy_get_struct(const char *directory, struct fscrypt_policy_v1 *fep);
-#else
-bool fscrypt_policy_get_struct(const char *directory, struct fscrypt_policy_v2 *fep);
-#endif
-
-#ifdef USE_FSCRYPT_POLICY_V1
-bool fscrypt_policy_set_struct(const char *directory, const struct fscrypt_policy_v1 *fep);
-#else
-bool fscrypt_policy_set_struct(const char *directory, const struct fscrypt_policy_v2 *fep);
-#endif
-
-void bytes_to_hex(const uint8_t *bytes, size_t num_bytes, char *hex);
-__END_DECLS
-
-#endif // _FS_CRYPT_H_
diff --git a/crypto/fscrypt/fscryptpolicyget.cpp b/crypto/fscrypt/fscryptpolicyget.cpp
deleted file mode 100755
index 189a428..0000000
--- a/crypto/fscrypt/fscryptpolicyget.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2016 Team Win Recovery 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 "fscrypt_policy.h"
-#include "fscrypt/fscrypt.h"
-
-int main(int argc, char *argv[]) {
- if (argc != 2) {
- printf("Must specify a path\n");
- return -1;
- } else {
-#ifdef USE_FSCRYPT_POLICY_V1
- fscrypt_policy_v1 fep;
-#else
- fscrypt_policy_v2 fep;
-#endif
- if (fscrypt_policy_get_struct(argv[1], &fep)) {
-#ifdef USE_FSCRYPT_POLICY_V1
- char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
- bytes_to_hex(fep.master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE, policy_hex);
-#else
- char policy_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
- bytes_to_hex(fep.master_key_identifier, FSCRYPT_KEY_IDENTIFIER_SIZE, policy_hex);
-#endif
- printf("%s\n", policy_hex);
- } else {
- printf("No policy set\n");
- }
- }
- return 0;
-}
diff --git a/crypto/fscrypt/keystore_auth.cpp b/crypto/fscrypt/keystore_auth.cpp
deleted file mode 100755
index a65fe21..0000000
--- a/crypto/fscrypt/keystore_auth.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- Copyright 2020 TeamWin
- This file is part of TWRP/TeamWin Recovery Project.
-
- TWRP is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- TWRP is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with TWRP. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/* The keystore refuses to allow the root user to supply auth tokens, so
- * we write the auth token to a file in TWRP and run a separate service
- * (this) that runs as the system user to add the auth token. TWRP waits
- * for /auth_token to be deleted and also looks for /auth_error to check
- * for errors. TWRP will error out after a while if /auth_token does not
- * get deleted. */
-
-#include <stdio.h>
-#include <string>
-
-#ifdef USE_SECURITY_NAMESPACE
-#include <android/security/keystore/IKeystoreService.h>
-#else
-#include <keystore/IKeystoreService.h>
-#include <keystore/authorization_set.h>
-#endif
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <keystore/keystore.h>
-
-#ifndef LOG_TAG
-#define LOG_TAG "keystore_auth"
-#endif
-
-using namespace android;
-using android::security::keystore::IKeystoreService;
-
-void create_error_file() {
- FILE* error_file = fopen("/auth_error", "wb");
- if (error_file == NULL) {
- printf("Failed to open /auth_error\n");
- ALOGE("Failed to open /auth_error\n");
- return;
- }
- fwrite("1", 1, 1, error_file);
- fclose(error_file);
- unlink("/auth_token");
-}
-
-int main() {
- unlink("/auth_error");
- FILE* auth_file = fopen("/auth_token", "rb");
- if (auth_file == NULL) {
- printf("Failed to open /auth_token\n");
- ALOGE("Failed to open /auth_token\n");
- create_error_file();
- return -1;
- }
- // Get the file size
- fseek(auth_file, 0, SEEK_END);
- int size = ftell(auth_file);
- fseek(auth_file, 0, SEEK_SET);
- uint8_t auth_token[size];
- fread(auth_token , sizeof(uint8_t), size, auth_file);
- fclose(auth_file);
- // First get the keystore service
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
-#ifdef USE_SECURITY_NAMESPACE
- sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
-#else
- sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
-#endif
- if (service == NULL) {
- printf("error: could not connect to keystore service\n");
- ALOGE("error: could not connect to keystore service\n");
- create_error_file();
- return -2;
- }
-#ifdef USE_SECURITY_NAMESPACE
- std::vector<uint8_t> auth_token_vector(&auth_token[0], (&auth_token[0]) + size);
- int result = 0;
- auto binder_result = service->addAuthToken(auth_token_vector, &result);
- if (!binder_result.isOk() || !keystore::KeyStoreServiceReturnCode(result).isOk()) {
-#else
- ::keystore::KeyStoreServiceReturnCode auth_result = service->addAuthToken(auth_token, size);
- if (!auth_result.isOk()) {
-#endif
- // The keystore checks the uid of the calling process and will return a permission denied on this operation for user 0
- printf("keystore error adding auth token\n");
- ALOGE("keystore error adding auth token\n");
- create_error_file();
- return -3;
- }
- printf("successfully added auth token to keystore\n");
- ALOGD("successfully added auth token to keystore\n");
- unlink("/auth_token");
- return 0;
-}
diff --git a/crypto/fscrypt/main.cpp b/crypto/fscrypt/main.cpp
deleted file mode 100644
index f0266ae..0000000
--- a/crypto/fscrypt/main.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 Team Win Recovery 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 "Decrypt.h"
-
-int main(int argc, char *argv[]) {
- bool ret = false;
- if (argc < 2) {
- Decrypt_DE();
- ret = Decrypt_User(0, "0000");
- } else if (argc < 3) {
- Decrypt_DE();
- ret = Decrypt_User(0, argv[1]);
- } else {
- ret = Decrypt_User(atoi(argv[1]), argv[2]);
- }
- if (!ret)
- printf("Failed to decrypt\n");
- return 0;
-}
diff --git a/crypto/fscrypt/sehandle.h b/crypto/fscrypt/sehandle.h
deleted file mode 100644
index 8921db5..0000000
--- a/crypto/fscrypt/sehandle.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2014 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 _SEHANDLE_H
-#define _SEHANDLE_H
-
-#include <selinux/android.h>
-
-extern struct selabel_handle* sehandle;
-
-#endif
diff --git a/etc/Android.mk b/etc/Android.mk
index e76527a..4aa769c 100755
--- a/etc/Android.mk
+++ b/etc/Android.mk
@@ -85,6 +85,23 @@
LOCAL_SRC_FILES := init/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
+
+ include $(CLEAR_VARS)
+ LOCAL_MODULE := keystore2.rc
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_MODULE_CLASS := EXECUTABLES
+ LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/etc/init
+
+ LOCAL_SRC_FILES := init/$(LOCAL_MODULE)
+ include $(BUILD_PREBUILT)
+
+ include $(CLEAR_VARS)
+ LOCAL_MODULE := android.system.keystore2-service.xml
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_MODULE_CLASS := EXECUTABLES
+ LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/etc/vintf/manifest
+ LOCAL_SRC_FILES := init/$(LOCAL_MODULE)
+ include $(BUILD_PREBUILT)
endif
ifeq ($(AB_OTA_UPDATER),true)
diff --git a/etc/init.rc b/etc/init.rc
index a85ce90..c6f750b 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -49,6 +49,8 @@
chown root shell /tmp
chmod 0775 /tmp
+ mkdir /tmp/misc
+ mkdir /tmp/misc/keystore/
write /proc/sys/kernel/panic_on_oops 1
write /proc/sys/vm/max_map_count 1000000
diff --git a/etc/init/android.system.keystore2-service.xml b/etc/init/android.system.keystore2-service.xml
new file mode 100644
index 0000000..6b8d0cb
--- /dev/null
+++ b/etc/init/android.system.keystore2-service.xml
@@ -0,0 +1,9 @@
+<manifest version="1.0" type="framework">
+ <hal format="aidl">
+ <name>android.system.keystore2</name>
+ <interface>
+ <name>IKeystoreService</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/etc/init/keystore2.rc b/etc/init/keystore2.rc
new file mode 100644
index 0000000..fa62662
--- /dev/null
+++ b/etc/init/keystore2.rc
@@ -0,0 +1,17 @@
+# Start the keystore2 service.
+# Keystore 2.0 changes its working directory to the first positional
+# command line option, i.e., /data/misc/keystore, where it stores its
+# database.
+# Keystore shall run as user keystore and groups keystore, readproc, and log.
+#
+# See system/core/init/README.md for information on the init.rc language.
+
+on late-init
+ start keystore2
+
+service keystore2 /system/bin/keystore2 /tmp/misc/keystore
+ class early_hal
+ user root
+ group keystore readproc log
+ writepid /dev/cpuset/foreground/tasks
+ seclabel u:r:recovery:s0
diff --git a/gui/libguitwrp_defaults.go b/gui/libguitwrp_defaults.go
index 290be25..9d7dcef 100644
--- a/gui/libguitwrp_defaults.go
+++ b/gui/libguitwrp_defaults.go
@@ -349,15 +349,6 @@
return srcs
}
-func globalIncludes(ctx android.BaseContext) []string {
- var includes []string
-
- if getMakeVars(ctx, "TW_INCLUDE_CRYPTO") != "" {
- includes = append(includes, "bootable/recovery/crypto/fscrypt")
- }
- return includes
-}
-
func libGuiDefaults(ctx android.LoadHookContext) {
type props struct {
Target struct {
@@ -375,8 +366,6 @@
p.Cflags = globalFlags(ctx)
s := globalSrcs(ctx)
p.Srcs = s
- i := globalIncludes(ctx)
- p.Include_dirs = i
ctx.AppendProperties(p)
if copyTheme(ctx) == false {
os.Exit(-1)
diff --git a/libaosprecovery_defaults.go b/libaosprecovery_defaults.go
index 442f1e4..1289ffa 100644
--- a/libaosprecovery_defaults.go
+++ b/libaosprecovery_defaults.go
@@ -30,16 +30,6 @@
return srcs
}
-func globalIncludes(ctx android.BaseContext) []string {
- var includes []string
-
- if getMakeVars(ctx, "TW_INCLUDE_CRYPTO") != "" {
- includes = append(includes, "bootable/recovery/crypto/fscrypt")
- }
-
- return includes
-}
-
func libAospRecoveryDefaults(ctx android.LoadHookContext) {
type props struct {
Target struct {
@@ -57,8 +47,6 @@
p.Cflags = globalFlags(ctx)
s := globalSrcs(ctx)
p.Srcs = s
- i := globalIncludes(ctx)
- p.Include_dirs = i
ctx.AppendProperties(p)
}
diff --git a/libtar/Android.mk b/libtar/Android.mk
index 6ff8fc9..fac3772 100755
--- a/libtar/Android.mk
+++ b/libtar/Android.mk
@@ -14,14 +14,54 @@
LOCAL_SHARED_LIBRARIES += libselinux
ifeq ($(TW_INCLUDE_CRYPTO_FBE), true)
- LOCAL_SHARED_LIBRARIES += libtwrpfscrypt
+ LOCAL_STATIC_LIBRARIES += libvold libscrypt_static
+ LOCAL_SHARED_LIBRARIES += \
+ android.hardware.boot@1.0 \
+ android.hardware.confirmationui@1.0 \
+ android.hardware.gatekeeper@1.0 \
+ android.hardware.keymaster@3.0 \
+ android.hardware.keymaster@4.0 \
+ android.hardware.keymaster@4.1 \
+ android.hardware.weaver@1.0 \
+ android.security.apc-ndk_platform \
+ android.system.keystore2-V1-ndk_platform \
+ android.security.authorization-ndk_platform \
+ android.security.maintenance-ndk_platform \
+ libselinux \
+ libbinder_ndk \
+ libext4_utils \
+ libbase \
+ libcrypto \
+ libcutils \
+ libf2fs_sparseblock \
+ libkeymaster_messages \
+ libkeymint_support \
+ libkeystoreinfo \
+ libkeystore-attestation-application-id \
+ libhardware \
+ libprotobuf-cpp-lite \
+ libfscrypt \
+ libhidlbase \
+ libutils \
+ libbinder \
+ libfs_mgr \
+ libkeymaster4support \
+ libkeymaster4_1support \
+ libf2fs_sparseblock \
+ libkeyutils \
+ liblog \
+ libhwbinder \
+ libchrome \
+ libbootloader_message \
+ libgatekeeper_aidl
+
LOCAL_CFLAGS += -DUSE_FSCRYPT
ifeq ($(TW_USE_FSCRYPT_POLICY), 1)
LOCAL_CFLAGS += -DUSE_FSCRYPT_POLICY_V1
else
LOCAL_CFLAGS += -DUSE_FSCRYPT_POLICY_V2
endif
- LOCAL_C_INCLUDES += $(LOCAL_PATH)/../crypto/fscrypt
+ LOCAL_C_INCLUDES += system/vold
endif
ifeq ($(TW_LIBTAR_DEBUG),true)
@@ -44,9 +84,8 @@
LOCAL_STATIC_LIBRARIES += libselinux
ifeq ($(TW_INCLUDE_CRYPTO_FBE), true)
- LOCAL_SHARED_LIBRARIES += libtwrpfscrypt
LOCAL_CFLAGS += -DUSE_FSCRYPT
- LOCAL_C_INCLUDES += $(LOCAL_PATH)/../crypto/fscrypt
+ LOCAL_C_INCLUDES += system/vold
endif
ifeq ($(TW_LIBTAR_DEBUG),true)
diff --git a/minuitwrp/libminuitwrp_defaults.go b/minuitwrp/libminuitwrp_defaults.go
index a6497a2..8cb176f 100644
--- a/minuitwrp/libminuitwrp_defaults.go
+++ b/minuitwrp/libminuitwrp_defaults.go
@@ -190,10 +190,6 @@
func globalIncludes(ctx android.BaseContext) []string {
var includes []string
- if getMakeVars(ctx, "TW_INCLUDE_CRYPTO") != "" {
- includes = append(includes, "bootable/recovery/crypto/fscrypt")
- }
-
if getMakeVars(ctx, "TW_TARGET_USES_QCOM_BSP") == "true" {
if getMakeVars(ctx, "TARGET_PREBUILT_KERNEL") != "" {
includes = append(includes, getMakeVars(ctx, "TARGET_OUT_INTERMEDIATES")+"/KERNEL_OBJ/usr/include")
diff --git a/partition.cpp b/partition.cpp
index 4854fbe..3bdc6d3 100755
--- a/partition.cpp
+++ b/partition.cpp
@@ -50,10 +50,9 @@
#include "gui/gui.hpp"
#include "adbbu/libtwadbbu.hpp"
#ifdef TW_INCLUDE_CRYPTO
- #include "crypto/fde/cryptfs.h"
+ // #include "crypto/fde/cryptfs.h"
+ #include "cryptfs.h"
#include "Decrypt.h"
-#else
- #define CRYPT_FOOTER_OFFSET 0x4000
#endif
extern "C" {
#include "mtdutils/mtdutils.h"
@@ -76,6 +75,8 @@
#include <sparse_format.h>
#include "progresstracking.hpp"
+#define CRYPT_FOOTER_OFFSET 0x4000
+
using namespace std;
static int auto_index = 0; // v2 fstab allows you to specify a mount point of "auto" with no /. These items are given a mount point of /auto* where * == auto_index
@@ -677,30 +678,10 @@
DataManager::SetValue(TW_IS_ENCRYPTED, 0);
} else if (!Mount(false)) {
if (Is_Present) {
- if (Key_Directory.empty()) {
- set_partition_data(Use_Original_Path ? Original_Path.c_str() : Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(),
- Fstab_File_System.c_str());
- if (cryptfs_check_footer() == 0) {
- Is_Encrypted = true;
- Is_Decrypted = false;
- Can_Be_Mounted = false;
- Current_File_System = "emmc";
- Setup_Image();
- DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
- DataManager::SetValue("tw_crypto_pwtype_0", cryptfs_get_password_type());
- DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
- DataManager::SetValue("tw_crypto_display", "");
- if (datamedia)
- Setup_Data_Media();
- } else {
- gui_err("mount_data_footer=Could not mount /data and unable to find crypto footer.");
- }
- } else {
- Is_Encrypted = true;
- Is_Decrypted = false;
- if (datamedia)
- Setup_Data_Media();
- }
+ Is_Encrypted = true;
+ Is_Decrypted = false;
+ if (datamedia)
+ Setup_Data_Media();
} else if (Key_Directory.empty()) {
LOGERR("Primary block device '%s' for mount point '%s' is not present!\n",
Primary_Block_Device.c_str(), Mount_Point.c_str());
@@ -774,7 +755,7 @@
ExcludeAll(Mount_Point + "/gsi"); // cow devices
int retry_count = 3;
- while (!Decrypt_DE() && --retry_count)
+ while (!android::keystore::Decrypt_DE() && --retry_count)
usleep(2000);
if (retry_count > 0) {
PartitionManager.Set_Crypto_State();
@@ -782,7 +763,7 @@
Is_Decrypted = false;
DataManager::SetValue(TW_IS_ENCRYPTED, 1);
string filename;
- int pwd_type = Get_Password_Type(0, filename);
+ int pwd_type = android::keystore::Get_Password_Type(0, filename);
if (pwd_type < 0) {
LOGERR("This TWRP does not have synthetic password decrypt support\n");
pwd_type = 0; // default password
@@ -3417,10 +3398,10 @@
thekey.append(buf, n);
}
close(fdkey);
- unsigned char* key = (unsigned char*) thekey.data();
- cryptfs_revert_ext_volume(part_guid);
+ // unsigned char* key = (unsigned char*) thekey.data();
+ // cryptfs_revert_ext_volume(part_guid);
- ret = cryptfs_setup_ext_volume(part_guid, Adopted_Block_Device.c_str(), key, thekey.size(), crypto_blkdev);
+ // ret = cryptfs_setup_ext_volume(part_guid, Adopted_Block_Device.c_str(), key, thekey.size(), crypto_blkdev);
if (ret == 0) {
LOGINFO("adopted storage new block device: '%s'\n", crypto_blkdev);
Decrypted_Block_Device = crypto_blkdev;
@@ -3431,7 +3412,7 @@
LOGERR("Failed to mount decrypted adopted storage device\n");
Is_Decrypted = false;
Is_Encrypted = false;
- cryptfs_revert_ext_volume(part_guid);
+ // cryptfs_revert_ext_volume(part_guid);
ret = 1;
} else {
UnMount(false);
@@ -3476,7 +3457,7 @@
if (!Adopted_GUID.empty()) {
PartitionManager.Remove_MTP_Storage(Mount_Point);
UnMount(false);
- cryptfs_revert_ext_volume(Adopted_GUID.c_str());
+ // cryptfs_revert_ext_volume(Adopted_GUID.c_str());
Is_Adopted_Storage = false;
Is_Encrypted = false;
Is_Decrypted = false;
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 01a108c..ebdada4 100755
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -93,13 +93,15 @@
}
#ifdef TW_INCLUDE_CRYPTO
-#include "crypto/fde/cryptfs.h"
+// #include "crypto/fde/cryptfs.h"
#include "gui/rapidxml.hpp"
#include "gui/pages.hpp"
#ifdef TW_INCLUDE_FBE
#include "Decrypt.h"
#ifdef TW_INCLUDE_FBE_METADATA_DECRYPT
#ifdef USE_FSCRYPT
+ #include "cryptfs.h"
+ #include "fscrypt-common.h"
#include "MetadataCrypt.h"
#endif
#endif
@@ -431,7 +433,7 @@
Set_Crypto_Type("file");
#ifdef TW_INCLUDE_FBE_METADATA_DECRYPT
#ifdef USE_FSCRYPT
- if (fscrypt_mount_metadata_encrypted(Decrypt_Data->Actual_Block_Device, Decrypt_Data->Mount_Point, false)) {
+ if (android::vold::fscrypt_mount_metadata_encrypted(Decrypt_Data->Actual_Block_Device, Decrypt_Data->Mount_Point, false, false, Decrypt_Data->Current_File_System)) {
std::string crypto_blkdev = android::base::GetProperty("ro.crypto.fs_crypto_blkdev", "error");
Decrypt_Data->Decrypted_Block_Device = crypto_blkdev;
LOGINFO("Successfully decrypted metadata encrypted data partition with new block device: '%s'\n", crypto_blkdev.c_str());
@@ -1885,7 +1887,7 @@
}
string filename;
- user.type = Get_Password_Type(userId, filename);
+ user.type = android::keystore::Get_Password_Type(userId, filename);
user.isDecrypted = false;
if (strcmp(user_check_result, "1") == 0)
@@ -1973,7 +1975,7 @@
while (!TWFunc::Path_Exists("/data/system/users/gatekeeper.password.key") && --retry_count)
usleep(2000); // A small sleep is needed after mounting /data to ensure reliable decrypt...maybe because of DE?
gui_msg(Msg("decrypting_user_fbe=Attempting to decrypt FBE for user {1}...")(user_id));
- if (Decrypt_User(user_id, Password)) {
+ if (android::keystore::Decrypt_User(user_id, Password)) {
gui_msg(Msg("decrypt_user_success_fbe=User {1} Decrypted Successfully")(user_id));
Mark_User_Decrypted(user_id);
if (user_id == 0) {
@@ -1985,8 +1987,8 @@
int tmp_user_id = atoi((*iter).userId.c_str());
gui_msg(Msg("decrypting_user_fbe=Attempting to decrypt FBE for user {1}...")(tmp_user_id));
- if (Decrypt_User(tmp_user_id, Password) ||
- (Password != "!" && Decrypt_User(tmp_user_id, "!"))) { // "!" means default password
+ if (android::keystore::Decrypt_User(tmp_user_id, Password) ||
+ (Password != "!" && android::keystore::Decrypt_User(tmp_user_id, "!"))) { // "!" means default password
gui_msg(Msg("decrypt_user_success_fbe=User {1} Decrypted Successfully")(tmp_user_id));
Mark_User_Decrypted(tmp_user_id);
} else {
diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk
index d611f4a..0252173 100755
--- a/prebuilt/Android.mk
+++ b/prebuilt/Android.mk
@@ -82,6 +82,7 @@
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libchrome.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libevent.so
RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/keystore
+RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/keystore_auth
RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/keystore_cli_v2
RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/hwservicemanager
RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/servicemanager
@@ -184,15 +185,38 @@
# FBE files
ifeq ($(TW_INCLUDE_CRYPTO_FBE), true)
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libtwrpfscrypt.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.security.maintenance-ndk_platform.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.system.keystore2-V1-ndk_platform.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.security.apc-ndk_platform.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.security.authorization-ndk_platform.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymint_support.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.security.keymint-V1-ndk_platform.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.frameworks.stats-V1-ndk_platform.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.security.secureclock-V1-ndk_platform.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libgatekeeper.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libgatekeeper_aidl.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymaster_messages.so
- RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeystore_binder.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libbinder.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libprotobuf-cpp-lite.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libsoftkeymasterdevice.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.gatekeeper@1.0.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeystore2_aaid.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeystore2_apc_compat.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeystore2_crypto.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkm_compat_service.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeystore2_vintf_cpp.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.security.compat-ndk_platform.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkm_compat.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymint.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/lib_android_keymaster_keymint_utils.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcppbor_external.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcppbor.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libpuresoftkeymasterdevice.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcppcose_rkp.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.security.sharedsecret-V1-ndk_platform.so
RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/avbctl
RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/keystore
+ RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/keystore2
RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/keystore_cli
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.system.wifi.keystore@1.0.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator@1.0.so
@@ -203,6 +227,15 @@
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libstatslog.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libsoft_attestation_cert.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libxml2.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libdiskconfig.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libhardware_legacy.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libincfs.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.health.storage@1.0.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.health.storage@1.0.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.health.storage-V1-ndk_platform.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libhardware_legacy.so
+ RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.system.suspend@1.0.so
+ RECOVERY_BINARY_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/fscryptpolicyget
ifneq ($(wildcard system/keymaster/keymaster_stl.cpp),)
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymaster_portable.so
@@ -223,8 +256,6 @@
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.keymaster@4.1.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymaster4support.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeymaster4_1support.so
- RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeystore_aidl.so
- RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libkeystore_parcelables.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libutilscallstack.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libdexfile.so
RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libservices.so
@@ -418,12 +449,21 @@
cp $(TARGET_OUT_ETC)/selinux/plat_service_contexts $(TARGET_RECOVERY_ROOT_OUT)/system/etc/selinux/plat_service_contexts && \
cp $(TARGET_OUT_ETC)/selinux/plat_hwservice_contexts $(TARGET_RECOVERY_ROOT_OUT)/system/etc/selinux/plat_hwservice_contexts && \
cp $(TARGET_OUT_VENDOR_ETC)/selinux/vndservice_contexts $(TARGET_RECOVERY_ROOT_OUT)/vendor/etc/selinux/vndservice_contexts && \
- cp $(TARGET_OUT_VENDOR_ETC)/selinux/vendor_hwservice_contexts $(TARGET_RECOVERY_ROOT_OUT)/vendor/etc/selinux/vendor_hwservice_contexts
+ cp $(TARGET_OUT_VENDOR_ETC)/selinux/vendor_hwservice_contexts $(TARGET_RECOVERY_ROOT_OUT)/vendor/etc/selinux/vendor_hwservice_contexts && \
+ cp $(TARGET_OUT_ETC)/selinux/plat_keystore2_key_contexts $(TARGET_RECOVERY_ROOT_OUT)/system/etc/selinux/plat_keystore2_key_contexts
ifeq ($(TARGET_USES_MKE2FS), true)
LOCAL_POST_INSTALL_CMD += \
&& cp $(TARGET_OUT_ETC)/mke2fs.conf $(TARGET_RECOVERY_ROOT_OUT)/system/etc/mke2fs.conf
endif
-LOCAL_REQUIRED_MODULES += init_second_stage.recovery reboot.recovery plat_service_contexts plat_hwservice_contexts plat_hardware_contexts vndservice_contexts vendor_hwservice_contexts
+LOCAL_REQUIRED_MODULES += init_second_stage.recovery \
+ reboot.recovery \
+ plat_service_contexts \
+ plat_hwservice_contexts \
+ plat_hardware_contexts \
+ vndservice_contexts \
+ plat_keystore2_key_contexts \
+ vendor_hwservice_contexts
+
include $(BUILD_PHONY_PACKAGE)
# copy license file for OpenAES
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
index 7ee5139..22a9a06 100755
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -1411,43 +1411,6 @@
}
}
-#ifdef TW_INCLUDE_CRYPTO
-#ifdef USE_FSCRYPT_POLICY_V1
-bool TWFunc::Get_Encryption_Policy(struct fscrypt_policy_v1 &policy, std::string path) {
-#else
-bool TWFunc::Get_Encryption_Policy(struct fscrypt_policy_v2 &policy, std::string path) {
-#endif
- if (!TWFunc::Path_Exists(path)) {
- LOGERR("Unable to find %s to get policy\n", path.c_str());
- return false;
- }
- if (!fscrypt_policy_get_struct(path.c_str(), &policy)) {
- LOGERR("No policy set for path %s\n", path.c_str());
- return false;
- }
- return true;
-}
-
-#ifdef USE_FSCRYPT_POLICY_V1
-bool TWFunc::Set_Encryption_Policy(std::string path, struct fscrypt_policy_v1 &policy) {
-#else
-bool TWFunc::Set_Encryption_Policy(std::string path, struct fscrypt_policy_v2 &policy) {
-#endif
- if (!TWFunc::Path_Exists(path)) {
- LOGERR("unable to find %s to set policy\n", path.c_str());
- return false;
- }
- uint8_t binary_policy[FS_KEY_DESCRIPTOR_SIZE];
- char policy_hex[FSCRYPT_KEY_IDENTIFIER_HEX_SIZE];
- bytes_to_hex(binary_policy, FS_KEY_DESCRIPTOR_SIZE, policy_hex);
- if (!fscrypt_policy_set_struct(path.c_str(), &policy)) {
- LOGERR("unable to set policy for path: %s\n", path.c_str());
- return false;
- }
- return true;
-}
-#endif
-
string TWFunc::Check_For_TwrpFolder() {
string oldFolder = "";
vector<string> customTWRPFolders;
diff --git a/twrp-functions.hpp b/twrp-functions.hpp
index 6221741..825d667 100755
--- a/twrp-functions.hpp
+++ b/twrp-functions.hpp
@@ -119,15 +119,6 @@
static bool Is_TWRP_App_In_System(); // Check if the TWRP app is installed in the system partition
static void checkforapp();
static int Property_Override(string Prop_Name, string Prop_Value); // Override properties (including ro. properties)
-#ifdef TW_INCLUDE_CRYPTO
-#ifdef USE_FSCRYPT_POLICY_V1
- static bool Get_Encryption_Policy(struct fscrypt_policy_v1 &policy, std::string path); // return encryption policy for path
- static bool Set_Encryption_Policy(std::string path, struct fscrypt_policy_v1 &policy); // set encryption policy for path
-#else
- static bool Get_Encryption_Policy(struct fscrypt_policy_v2 &policy, std::string path); // return encryption policy for path
- static bool Set_Encryption_Policy(std::string path, struct fscrypt_policy_v2 &policy); // set encryption policy for path
-#endif
-#endif
static void List_Mounts(); // List current mounts by the kernel
static void Clear_Bootloader_Message(); // Removes the bootloader message from misc for next boot
static string Check_For_TwrpFolder(); // Gets user defined path on storage where backups should be stored
diff --git a/twrp.cpp b/twrp.cpp
index 69c8218..6566e04 100644
--- a/twrp.cpp
+++ b/twrp.cpp
@@ -67,6 +67,11 @@
}
#endif
+#ifdef TW_INCLUDE_CRYPTO
+#include "FsCrypt.h"
+#include "Decrypt.h"
+#endif
+
//extern int adb_server_main(int is_daemon, int server_port, int /* reply_fd */);
TWPartitionManager PartitionManager;
@@ -251,8 +256,11 @@
}
LOGINFO("Backup of TWRP ramdisk done.\n");
#endif
-
+#ifdef TW_INCLUDE_CRYPTO
+ android::keystore::copySqliteDb();
+#endif
Decrypt_Page(skip_decryption, datamedia);
+
// Check for and load custom theme if present
TWFunc::check_selinux_support();
gui_loadCustomResources();
@@ -350,7 +358,6 @@
gui_msg(Msg("rebooting=Rebooting..."));
TWFunc::Update_Log_File();
string Reboot_Arg;
-
DataManager::GetValue("tw_reboot_arg", Reboot_Arg);
if (Reboot_Arg == "recovery")
TWFunc::tw_reboot(rb_recovery);
diff --git a/twrpinstall/Android.bp b/twrpinstall/Android.bp
index 81fe3fb..a5ef145 100755
--- a/twrpinstall/Android.bp
+++ b/twrpinstall/Android.bp
@@ -65,7 +65,6 @@
"bootable/recovery",
"bootable/recovery/install/include",
"bootable/recovery/recovery_utils/include",
- "bootable/recovery/crypto/fscrypt"
],
srcs: [