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