blob: 5d6641963ad3f8e29e17422371f29f3187631111 [file] [log] [blame]
Elliott Hughesee296862015-03-28 10:39:46 -07001#define TAG "ext4_utils"
2
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +00003#include "ext4_crypt_init_extensions.h"
Paul Lawrence92da49d2015-02-25 15:11:13 -08004
5#include <string>
Paul Lawrence92da49d2015-02-25 15:11:13 -08006
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +00007#include <dirent.h>
Paul Lawrence92da49d2015-02-25 15:11:13 -08008#include <errno.h>
Elliott Hughesee296862015-03-28 10:39:46 -07009#include <sys/mount.h>
Paul Lawrence92da49d2015-02-25 15:11:13 -080010#include <sys/stat.h>
Elliott Hughesee296862015-03-28 10:39:46 -070011
12#include <cutils/klog.h>
Paul Lawrence92da49d2015-02-25 15:11:13 -080013#include <cutils/properties.h>
14#include <cutils/sockets.h>
Paul Crowley36d056c2015-04-09 10:18:54 +010015#include <poll.h>
Paul Lawrence92da49d2015-02-25 15:11:13 -080016
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000017#include "key_control.h"
Paul Lawrence61980262015-03-16 15:35:55 -070018#include "unencrypted_properties.h"
19
Paul Lawrence92da49d2015-02-25 15:11:13 -080020static const std::string arbitrary_sequence_number = "42";
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000021static const int vold_command_timeout_ms = 60 * 1000;
Paul Lawrence92da49d2015-02-25 15:11:13 -080022
23static std::string vold_command(std::string const& command)
24{
Elliott Hughesee296862015-03-28 10:39:46 -070025 KLOG_INFO(TAG, "Running command %s\n", command.c_str());
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000026 int sock = -1;
27
28 while (true) {
Paul Lawrenceb411bcc2015-06-03 14:18:17 -070029 sock = socket_local_client("cryptd",
Paul Lawrence92da49d2015-02-25 15:11:13 -080030 ANDROID_SOCKET_NAMESPACE_RESERVED,
31 SOCK_STREAM);
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000032 if (sock >= 0) {
33 break;
34 }
35 usleep(10000);
36 }
Paul Lawrence92da49d2015-02-25 15:11:13 -080037
38 if (sock < 0) {
Paul Crowleye92c6822015-05-28 16:45:52 +010039 KLOG_INFO(TAG, "Cannot open vold, failing command (%s)\n", strerror(errno));
Paul Lawrence92da49d2015-02-25 15:11:13 -080040 return "";
41 }
42
43 class CloseSocket
44 {
45 int sock_;
46 public:
47 CloseSocket(int sock) : sock_(sock) {}
48 ~CloseSocket() { close(sock_); }
49 };
50
51 CloseSocket cs(sock);
52
53 // Use arbitrary sequence number. This should only be used when the
54 // framework is down, so this is (mostly) OK.
55 std::string actual_command = arbitrary_sequence_number + " " + command;
56 if (write(sock, actual_command.c_str(), actual_command.size() + 1) < 0) {
Paul Crowleye92c6822015-05-28 16:45:52 +010057 KLOG_ERROR(TAG, "Cannot write command (%s)\n", strerror(errno));
Paul Lawrence92da49d2015-02-25 15:11:13 -080058 return "";
59 }
60
Paul Crowley36d056c2015-04-09 10:18:54 +010061 struct pollfd poll_sock = {sock, POLLIN, 0};
Paul Lawrence92da49d2015-02-25 15:11:13 -080062
Paul Lawrence2fa9e932015-06-12 13:06:21 -070063 int rc = TEMP_FAILURE_RETRY(poll(&poll_sock, 1, vold_command_timeout_ms));
Paul Crowley36d056c2015-04-09 10:18:54 +010064 if (rc < 0) {
Paul Crowleye92c6822015-05-28 16:45:52 +010065 KLOG_ERROR(TAG, "Error in poll (%s)\n", strerror(errno));
Paul Crowley36d056c2015-04-09 10:18:54 +010066 return "";
Paul Lawrence92da49d2015-02-25 15:11:13 -080067 }
Paul Lawrence2fa9e932015-06-12 13:06:21 -070068
Paul Crowley36d056c2015-04-09 10:18:54 +010069 if (!(poll_sock.revents & POLLIN)) {
70 KLOG_ERROR(TAG, "Timeout\n");
71 return "";
72 }
73 char buffer[4096];
74 memset(buffer, 0, sizeof(buffer));
Paul Lawrence2fa9e932015-06-12 13:06:21 -070075 rc = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer)));
Paul Crowley36d056c2015-04-09 10:18:54 +010076 if (rc <= 0) {
77 if (rc == 0) {
78 KLOG_ERROR(TAG, "Lost connection to Vold - did it crash?\n");
79 } else {
80 KLOG_ERROR(TAG, "Error reading data (%s)\n", strerror(errno));
81 }
82 return "";
83 }
84
85 // We don't truly know that this is the correct result. However,
86 // since this will only be used when the framework is down,
87 // it should be OK unless someone is running vdc at the same time.
88 // Worst case we force a reboot in the very rare synchronization
89 // error
90 return std::string(buffer, rc);
Paul Lawrence92da49d2015-02-25 15:11:13 -080091}
92
Paul Lawrencef9768752015-03-30 09:16:09 -070093int e4crypt_create_device_key(const char* dir,
94 int ensure_dir_exists(const char*))
Paul Lawrence92da49d2015-02-25 15:11:13 -080095{
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000096 // Already encrypted with password? If so bail
97 std::string temp_folder = std::string() + dir + "/tmp_mnt";
98 DIR* temp_dir = opendir(temp_folder.c_str());
99 if (temp_dir) {
100 closedir(temp_dir);
101 return 0;
102 }
103
Paul Lawrence92da49d2015-02-25 15:11:13 -0800104 // Make sure folder exists. Use make_dir to set selinux permissions.
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000105 if (ensure_dir_exists(UnencryptedProperties::GetPath(dir).c_str())) {
Paul Crowleye92c6822015-05-28 16:45:52 +0100106 KLOG_ERROR(TAG, "Failed to create %s (%s)\n",
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000107 UnencryptedProperties::GetPath(dir).c_str(),
108 strerror(errno));
Paul Lawrence92da49d2015-02-25 15:11:13 -0800109 return -1;
110 }
111
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000112 auto result = vold_command("cryptfs enablefilecrypto");
113 // ext4enc:TODO proper error handling
114 KLOG_INFO(TAG, "enablefilecrypto returned with result %s\n",
115 result.c_str());
Paul Lawrence61980262015-03-16 15:35:55 -0700116
Paul Lawrence92da49d2015-02-25 15:11:13 -0800117 return 0;
118}
119
120int e4crypt_install_keyring()
121{
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000122 key_serial_t device_keyring = add_key("keyring", "e4crypt", 0, 0,
123 KEY_SPEC_SESSION_KEYRING);
Paul Lawrence92da49d2015-02-25 15:11:13 -0800124
125 if (device_keyring == -1) {
Paul Crowleye92c6822015-05-28 16:45:52 +0100126 KLOG_ERROR(TAG, "Failed to create keyring (%s)\n", strerror(errno));
Paul Lawrence92da49d2015-02-25 15:11:13 -0800127 return -1;
128 }
129
Paul Lawrence61980262015-03-16 15:35:55 -0700130 KLOG_INFO(TAG, "Keyring created wth id %d in process %d\n",
131 device_keyring, getpid());
Paul Lawrence92da49d2015-02-25 15:11:13 -0800132
Paul Lawrence92da49d2015-02-25 15:11:13 -0800133 return 0;
134}
135
Paul Lawrence92da49d2015-02-25 15:11:13 -0800136int e4crypt_set_directory_policy(const char* dir)
137{
138 // Only set policy on first level /data directories
Paul Lawrence61980262015-03-16 15:35:55 -0700139 // To make this less restrictive, consider using a policy file.
140 // However this is overkill for as long as the policy is simply
141 // to apply a global policy to all /data folders created via makedir
Paul Lawrence92da49d2015-02-25 15:11:13 -0800142 if (!dir || strncmp(dir, "/data/", 6) || strchr(dir + 6, '/')) {
143 return 0;
144 }
Paul Lawrence65df4832015-07-15 15:22:03 -0700145
146 // Don't encrypt lost+found - ext4 doesn't like it
Paul Lawrencedd22cb32015-07-16 07:54:52 -0700147 if (!strcmp(dir, "/data/lost+found")) {
Paul Lawrence65df4832015-07-15 15:22:03 -0700148 return 0;
149 }
150
Paul Crowley15e73f52015-05-06 15:28:35 +0100151 // ext4enc:TODO exclude /data/user with a horrible special case.
152 if (!strcmp(dir, "/data/user")) {
153 return 0;
154 }
Paul Lawrence92da49d2015-02-25 15:11:13 -0800155
Paul Lawrence61980262015-03-16 15:35:55 -0700156 UnencryptedProperties props("/data");
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000157 std::string policy = props.Get<std::string>(properties::ref);
Paul Lawrencedb1d49c2015-04-10 07:47:30 -0700158 if (policy.empty()) {
Paul Crowley15e73f52015-05-06 15:28:35 +0100159 // ext4enc:TODO why is this OK?
Paul Lawrencedb1d49c2015-04-10 07:47:30 -0700160 return 0;
161 }
162
Paul Lawrenceaf02e8a2015-05-01 05:24:04 -0700163 KLOG_INFO(TAG, "Setting policy on %s\n", dir);
Paul Lawrencedb1d49c2015-04-10 07:47:30 -0700164 int result = do_policy_set(dir, policy.c_str(), policy.size());
Paul Lawrence61980262015-03-16 15:35:55 -0700165 if (result) {
Paul Lawrence65df4832015-07-15 15:22:03 -0700166 KLOG_ERROR(TAG, "Setting %02x%02x%02x%02x policy on %s failed!\n",
167 policy[0], policy[1], policy[2], policy[3], dir);
Paul Lawrence92da49d2015-02-25 15:11:13 -0800168 return -1;
169 }
170
171 return 0;
172}
Paul Crowley45f1a1f2015-05-28 16:45:52 +0100173
174int e4crypt_set_user_crypto_policies(const char* dir)
175{
176 auto command = std::string() + "cryptfs setusercryptopolicies " + dir;
177 auto result = vold_command(command);
178 // ext4enc:TODO proper error handling
179 KLOG_INFO(TAG, "setusercryptopolicies returned with result %s\n",
180 result.c_str());
181 return 0;
182}