1ee29686943f6c40489b7e3009cc8c87cdde79abfElliott Hughes#define TAG "ext4_utils" 2ee29686943f6c40489b7e3009cc8c87cdde79abfElliott Hughes 3bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence#include "ext4_crypt_init_extensions.h" 492da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 592da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence#include <string> 692da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 7bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence#include <dirent.h> 892da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence#include <errno.h> 9ee29686943f6c40489b7e3009cc8c87cdde79abfElliott Hughes#include <sys/mount.h> 1092da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence#include <sys/stat.h> 11ee29686943f6c40489b7e3009cc8c87cdde79abfElliott Hughes 12ee29686943f6c40489b7e3009cc8c87cdde79abfElliott Hughes#include <cutils/klog.h> 1392da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence#include <cutils/properties.h> 1492da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence#include <cutils/sockets.h> 1536d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley#include <poll.h> 1692da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 17bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence#include "key_control.h" 1861980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence#include "unencrypted_properties.h" 1961980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence 2092da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrencestatic const std::string arbitrary_sequence_number = "42"; 21bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrencestatic const int vold_command_timeout_ms = 60 * 1000; 2292da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 2392da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrencestatic std::string vold_command(std::string const& command) 2492da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence{ 25ee29686943f6c40489b7e3009cc8c87cdde79abfElliott Hughes KLOG_INFO(TAG, "Running command %s\n", command.c_str()); 26bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence int sock = -1; 27bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence 28bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence while (true) { 29b411bcc138293db5e09c1f5af638115b3c7c18f8Paul Lawrence sock = socket_local_client("cryptd", 3092da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence ANDROID_SOCKET_NAMESPACE_RESERVED, 3192da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence SOCK_STREAM); 32bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence if (sock >= 0) { 33bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence break; 34bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence } 35bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence usleep(10000); 36bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence } 3792da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 3892da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence if (sock < 0) { 39e92c682fb37a21a38406281f3038c5168fd26b3ePaul Crowley KLOG_INFO(TAG, "Cannot open vold, failing command (%s)\n", strerror(errno)); 4092da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence return ""; 4192da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence } 4292da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 4392da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence class CloseSocket 4492da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence { 4592da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence int sock_; 4692da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence public: 4792da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence CloseSocket(int sock) : sock_(sock) {} 4892da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence ~CloseSocket() { close(sock_); } 4992da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence }; 5092da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 5192da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence CloseSocket cs(sock); 5292da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 5392da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence // Use arbitrary sequence number. This should only be used when the 5492da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence // framework is down, so this is (mostly) OK. 5592da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence std::string actual_command = arbitrary_sequence_number + " " + command; 5692da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence if (write(sock, actual_command.c_str(), actual_command.size() + 1) < 0) { 57e92c682fb37a21a38406281f3038c5168fd26b3ePaul Crowley KLOG_ERROR(TAG, "Cannot write command (%s)\n", strerror(errno)); 5892da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence return ""; 5992da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence } 6092da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 6136d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley struct pollfd poll_sock = {sock, POLLIN, 0}; 6236d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley 632fa9e939581d944f0204291c53356d6b8c3a938fPaul Lawrence int rc = TEMP_FAILURE_RETRY(poll(&poll_sock, 1, vold_command_timeout_ms)); 6436d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley if (rc < 0) { 65e92c682fb37a21a38406281f3038c5168fd26b3ePaul Crowley KLOG_ERROR(TAG, "Error in poll (%s)\n", strerror(errno)); 6636d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley return ""; 6736d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley } 682fa9e939581d944f0204291c53356d6b8c3a938fPaul Lawrence 6936d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley if (!(poll_sock.revents & POLLIN)) { 7036d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley KLOG_ERROR(TAG, "Timeout\n"); 7136d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley return ""; 7236d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley } 7336d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley char buffer[4096]; 7436d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley memset(buffer, 0, sizeof(buffer)); 752fa9e939581d944f0204291c53356d6b8c3a938fPaul Lawrence rc = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); 7636d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley if (rc <= 0) { 7736d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley if (rc == 0) { 7836d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley KLOG_ERROR(TAG, "Lost connection to Vold - did it crash?\n"); 7936d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley } else { 8036d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley KLOG_ERROR(TAG, "Error reading data (%s)\n", strerror(errno)); 8192da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence } 8236d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley return ""; 8392da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence } 8436d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley 8536d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley // We don't truly know that this is the correct result. However, 8636d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley // since this will only be used when the framework is down, 8736d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley // it should be OK unless someone is running vdc at the same time. 8836d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley // Worst case we force a reboot in the very rare synchronization 8936d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley // error 9036d056c52e78565747786e9870c3c0a9fbf80612Paul Crowley return std::string(buffer, rc); 9192da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence} 9292da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 93f9768752cbf6ebac97214a021dc288c7b6592f1ePaul Lawrenceint e4crypt_create_device_key(const char* dir, 94f9768752cbf6ebac97214a021dc288c7b6592f1ePaul Lawrence int ensure_dir_exists(const char*)) 9592da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence{ 96bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence // Already encrypted with password? If so bail 97bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence std::string temp_folder = std::string() + dir + "/tmp_mnt"; 98bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence DIR* temp_dir = opendir(temp_folder.c_str()); 99bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence if (temp_dir) { 100bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence closedir(temp_dir); 101bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence return 0; 102bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence } 103bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence 10492da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence // Make sure folder exists. Use make_dir to set selinux permissions. 105bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence if (ensure_dir_exists(UnencryptedProperties::GetPath(dir).c_str())) { 106e92c682fb37a21a38406281f3038c5168fd26b3ePaul Crowley KLOG_ERROR(TAG, "Failed to create %s (%s)\n", 107bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence UnencryptedProperties::GetPath(dir).c_str(), 108bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence strerror(errno)); 10992da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence return -1; 11092da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence } 11192da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 112bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence auto result = vold_command("cryptfs enablefilecrypto"); 113bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence // ext4enc:TODO proper error handling 114bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence KLOG_INFO(TAG, "enablefilecrypto returned with result %s\n", 115bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence result.c_str()); 11661980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence 11792da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence return 0; 11892da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence} 11992da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 12092da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrenceint e4crypt_install_keyring() 12192da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence{ 122bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence key_serial_t device_keyring = add_key("keyring", "e4crypt", 0, 0, 123bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence KEY_SPEC_SESSION_KEYRING); 12492da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 12592da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence if (device_keyring == -1) { 126e92c682fb37a21a38406281f3038c5168fd26b3ePaul Crowley KLOG_ERROR(TAG, "Failed to create keyring (%s)\n", strerror(errno)); 12792da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence return -1; 12892da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence } 12992da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 13061980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence KLOG_INFO(TAG, "Keyring created wth id %d in process %d\n", 13161980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence device_keyring, getpid()); 13292da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 13392da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence return 0; 13492da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence} 13592da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 13692da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrenceint e4crypt_set_directory_policy(const char* dir) 13792da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence{ 13892da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence // Only set policy on first level /data directories 13961980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence // To make this less restrictive, consider using a policy file. 14061980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence // However this is overkill for as long as the policy is simply 14161980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence // to apply a global policy to all /data folders created via makedir 14292da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence if (!dir || strncmp(dir, "/data/", 6) || strchr(dir + 6, '/')) { 14392da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence return 0; 14492da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence } 14565df483af2efcb2ab9fd82ae53f9aeaa55f0cebdPaul Lawrence 14665df483af2efcb2ab9fd82ae53f9aeaa55f0cebdPaul Lawrence // Don't encrypt lost+found - ext4 doesn't like it 147dd22cb338ad59a4766e9ee47936f1e10b386e128Paul Lawrence if (!strcmp(dir, "/data/lost+found")) { 14865df483af2efcb2ab9fd82ae53f9aeaa55f0cebdPaul Lawrence return 0; 14965df483af2efcb2ab9fd82ae53f9aeaa55f0cebdPaul Lawrence } 15065df483af2efcb2ab9fd82ae53f9aeaa55f0cebdPaul Lawrence 15115e73f525c38d9ccdf8806a6227e83867b8e259bPaul Crowley // ext4enc:TODO exclude /data/user with a horrible special case. 15215e73f525c38d9ccdf8806a6227e83867b8e259bPaul Crowley if (!strcmp(dir, "/data/user")) { 15315e73f525c38d9ccdf8806a6227e83867b8e259bPaul Crowley return 0; 15415e73f525c38d9ccdf8806a6227e83867b8e259bPaul Crowley } 15592da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 15661980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence UnencryptedProperties props("/data"); 157bc2eb8c3fd621605ff1ccaed04a71e6685acc974Paul Lawrence std::string policy = props.Get<std::string>(properties::ref); 158db1d49c70eec489cf3d60a4ec70a8e7c0f3f2b76Paul Lawrence if (policy.empty()) { 15915e73f525c38d9ccdf8806a6227e83867b8e259bPaul Crowley // ext4enc:TODO why is this OK? 160db1d49c70eec489cf3d60a4ec70a8e7c0f3f2b76Paul Lawrence return 0; 161db1d49c70eec489cf3d60a4ec70a8e7c0f3f2b76Paul Lawrence } 162db1d49c70eec489cf3d60a4ec70a8e7c0f3f2b76Paul Lawrence 163af02e8aa9164f723a0c2a421a97c227c5adff4c2Paul Lawrence KLOG_INFO(TAG, "Setting policy on %s\n", dir); 164db1d49c70eec489cf3d60a4ec70a8e7c0f3f2b76Paul Lawrence int result = do_policy_set(dir, policy.c_str(), policy.size()); 16561980269c14ae78a9ca893a56df67cf475cdfafdPaul Lawrence if (result) { 16665df483af2efcb2ab9fd82ae53f9aeaa55f0cebdPaul Lawrence KLOG_ERROR(TAG, "Setting %02x%02x%02x%02x policy on %s failed!\n", 16765df483af2efcb2ab9fd82ae53f9aeaa55f0cebdPaul Lawrence policy[0], policy[1], policy[2], policy[3], dir); 16892da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence return -1; 16992da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence } 17092da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence 17192da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence return 0; 17292da49db65ffbe0bff1771ecef87ad49e94a0626Paul Lawrence} 17345f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowley 17445f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowleyint e4crypt_set_user_crypto_policies(const char* dir) 17545f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowley{ 17645f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowley auto command = std::string() + "cryptfs setusercryptopolicies " + dir; 17745f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowley auto result = vold_command(command); 17845f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowley // ext4enc:TODO proper error handling 17945f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowley KLOG_INFO(TAG, "setusercryptopolicies returned with result %s\n", 18045f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowley result.c_str()); 18145f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowley return 0; 18245f1a1fd1f1cea461abea44de4b0696b6c45767fPaul Crowley} 183