• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "fscrypt/fscrypt.h"
18 
19 #include <array>
20 
21 #include <asm/ioctl.h>
22 #include <dirent.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <linux/fs.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 
32 #include <android-base/file.h>
33 #include <android-base/logging.h>
34 #include <cutils/properties.h>
35 #include <logwrap/logwrap.h>
36 #include <utils/misc.h>
37 
38 #define FS_KEY_DESCRIPTOR_SIZE_HEX (2 * FS_KEY_DESCRIPTOR_SIZE + 1)
39 
40 /* modes not supported by upstream kernel, so not in <linux/fs.h> */
41 #define FS_ENCRYPTION_MODE_AES_256_HEH      126
42 #define FS_ENCRYPTION_MODE_PRIVATE          127
43 
44 /* new definition, not yet in Bionic's <linux/fs.h> */
45 #ifndef FS_ENCRYPTION_MODE_ADIANTUM
46 #define FS_ENCRYPTION_MODE_ADIANTUM         9
47 #endif
48 
49 /* new definition, not yet in Bionic's <linux/fs.h> */
50 #ifndef FS_POLICY_FLAG_DIRECT_KEY
51 #define FS_POLICY_FLAG_DIRECT_KEY           0x4
52 #endif
53 
54 #define HEX_LOOKUP "0123456789abcdef"
55 
fscrypt_is_native()56 bool fscrypt_is_native() {
57     char value[PROPERTY_VALUE_MAX];
58     property_get("ro.crypto.type", value, "none");
59     return !strcmp(value, "file");
60 }
61 
log_ls(const char * dirname)62 static void log_ls(const char* dirname) {
63     std::array<const char*, 3> argv = {"ls", "-laZ", dirname};
64     int status = 0;
65     auto res =
66         android_fork_execvp(argv.size(), const_cast<char**>(argv.data()), &status, false, true);
67     if (res != 0) {
68         PLOG(ERROR) << argv[0] << " " << argv[1] << " " << argv[2] << "failed";
69         return;
70     }
71     if (!WIFEXITED(status)) {
72         LOG(ERROR) << argv[0] << " " << argv[1] << " " << argv[2]
73                    << " did not exit normally, status: " << status;
74         return;
75     }
76     if (WEXITSTATUS(status) != 0) {
77         LOG(ERROR) << argv[0] << " " << argv[1] << " " << argv[2]
78                    << " returned failure: " << WEXITSTATUS(status);
79         return;
80     }
81 }
82 
policy_to_hex(const char * policy,char * hex)83 static void policy_to_hex(const char* policy, char* hex) {
84     for (size_t i = 0, j = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) {
85         hex[j++] = HEX_LOOKUP[(policy[i] & 0xF0) >> 4];
86         hex[j++] = HEX_LOOKUP[policy[i] & 0x0F];
87     }
88     hex[FS_KEY_DESCRIPTOR_SIZE_HEX - 1] = '\0';
89 }
90 
is_dir_empty(const char * dirname,bool * is_empty)91 static bool is_dir_empty(const char *dirname, bool *is_empty)
92 {
93     int n = 0;
94     auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(dirname), closedir);
95     if (!dirp) {
96         PLOG(ERROR) << "Unable to read directory: " << dirname;
97         return false;
98     }
99     for (;;) {
100         errno = 0;
101         auto entry = readdir(dirp.get());
102         if (!entry) {
103             if (errno) {
104                 PLOG(ERROR) << "Unable to read directory: " << dirname;
105                 return false;
106             }
107             break;
108         }
109         if (strcmp(entry->d_name, "lost+found") != 0) { // Skip lost+found
110             ++n;
111             if (n > 2) {
112                 *is_empty = false;
113                 return true;
114             }
115         }
116     }
117     *is_empty = true;
118     return true;
119 }
120 
fscrypt_get_policy_flags(int filenames_encryption_mode)121 static uint8_t fscrypt_get_policy_flags(int filenames_encryption_mode) {
122     if (filenames_encryption_mode == FS_ENCRYPTION_MODE_AES_256_CTS) {
123         // Use legacy padding with our original filenames encryption mode.
124         return FS_POLICY_FLAGS_PAD_4;
125     } else if (filenames_encryption_mode == FS_ENCRYPTION_MODE_ADIANTUM) {
126         // Use DIRECT_KEY for Adiantum, since it's much more efficient but just
127         // as secure since Android doesn't reuse the same master key for
128         // multiple encryption modes
129         return (FS_POLICY_FLAGS_PAD_16 | FS_POLICY_FLAG_DIRECT_KEY);
130     }
131     // With a new mode we can use the better padding flag without breaking existing devices: pad
132     // filenames with zeroes to the next 16-byte boundary.  This is more secure (helps hide the
133     // length of filenames) and makes the inputs evenly divisible into blocks which is more
134     // efficient for encryption and decryption.
135     return FS_POLICY_FLAGS_PAD_16;
136 }
137 
fscrypt_policy_set(const char * directory,const char * policy,size_t policy_length,int contents_encryption_mode,int filenames_encryption_mode)138 static bool fscrypt_policy_set(const char *directory, const char *policy,
139                                size_t policy_length,
140                                int contents_encryption_mode,
141                                int filenames_encryption_mode) {
142     if (policy_length != FS_KEY_DESCRIPTOR_SIZE) {
143         LOG(ERROR) << "Policy wrong length: " << policy_length;
144         return false;
145     }
146     char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
147     policy_to_hex(policy, policy_hex);
148 
149     int fd = open(directory, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
150     if (fd == -1) {
151         PLOG(ERROR) << "Failed to open directory " << directory;
152         return false;
153     }
154 
155     fscrypt_policy fp;
156     fp.version = 0;
157     fp.contents_encryption_mode = contents_encryption_mode;
158     fp.filenames_encryption_mode = filenames_encryption_mode;
159     fp.flags = fscrypt_get_policy_flags(filenames_encryption_mode);
160     memcpy(fp.master_key_descriptor, policy, FS_KEY_DESCRIPTOR_SIZE);
161     if (ioctl(fd, FS_IOC_SET_ENCRYPTION_POLICY, &fp)) {
162         PLOG(ERROR) << "Failed to set encryption policy for " << directory  << " to " << policy_hex
163             << " modes " << contents_encryption_mode << "/" << filenames_encryption_mode;
164         close(fd);
165         return false;
166     }
167     close(fd);
168 
169     LOG(INFO) << "Policy for " << directory << " set to " << policy_hex
170         << " modes " << contents_encryption_mode << "/" << filenames_encryption_mode;
171     return true;
172 }
173 
fscrypt_policy_get(const char * directory,char * policy,size_t policy_length,int contents_encryption_mode,int filenames_encryption_mode)174 static bool fscrypt_policy_get(const char *directory, char *policy,
175                                size_t policy_length,
176                                int contents_encryption_mode,
177                                int filenames_encryption_mode) {
178     if (policy_length != FS_KEY_DESCRIPTOR_SIZE) {
179         LOG(ERROR) << "Policy wrong length: " << policy_length;
180         return false;
181     }
182 
183     int fd = open(directory, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
184     if (fd == -1) {
185         PLOG(ERROR) << "Failed to open directory " << directory;
186         return false;
187     }
188 
189     fscrypt_policy fp;
190     memset(&fp, 0, sizeof(fscrypt_policy));
191     if (ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &fp) != 0) {
192         PLOG(ERROR) << "Failed to get encryption policy for " << directory;
193         close(fd);
194         log_ls(directory);
195         return false;
196     }
197     close(fd);
198 
199     if ((fp.version != 0)
200             || (fp.contents_encryption_mode != contents_encryption_mode)
201             || (fp.filenames_encryption_mode != filenames_encryption_mode)
202             || (fp.flags !=
203                 fscrypt_get_policy_flags(filenames_encryption_mode))) {
204         LOG(ERROR) << "Failed to find matching encryption policy for " << directory;
205         return false;
206     }
207     memcpy(policy, fp.master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE);
208 
209     return true;
210 }
211 
fscrypt_policy_check(const char * directory,const char * policy,size_t policy_length,int contents_encryption_mode,int filenames_encryption_mode)212 static bool fscrypt_policy_check(const char *directory, const char *policy,
213                                  size_t policy_length,
214                                  int contents_encryption_mode,
215                                  int filenames_encryption_mode) {
216     if (policy_length != FS_KEY_DESCRIPTOR_SIZE) {
217         LOG(ERROR) << "Policy wrong length: " << policy_length;
218         return false;
219     }
220     char existing_policy[FS_KEY_DESCRIPTOR_SIZE];
221     if (!fscrypt_policy_get(directory, existing_policy, FS_KEY_DESCRIPTOR_SIZE,
222                             contents_encryption_mode,
223                             filenames_encryption_mode)) return false;
224     char existing_policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
225 
226     policy_to_hex(existing_policy, existing_policy_hex);
227 
228     if (memcmp(policy, existing_policy, FS_KEY_DESCRIPTOR_SIZE) != 0) {
229         char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
230         policy_to_hex(policy, policy_hex);
231         LOG(ERROR) << "Found policy " << existing_policy_hex << " at " << directory
232                    << " which doesn't match expected value " << policy_hex;
233         log_ls(directory);
234         return false;
235     }
236     LOG(INFO) << "Found policy " << existing_policy_hex << " at " << directory
237               << " which matches expected value";
238     return true;
239 }
240 
fscrypt_policy_ensure(const char * directory,const char * policy,size_t policy_length,const char * contents_encryption_mode,const char * filenames_encryption_mode)241 int fscrypt_policy_ensure(const char *directory, const char *policy,
242                           size_t policy_length,
243                           const char *contents_encryption_mode,
244                           const char *filenames_encryption_mode) {
245     int contents_mode = 0;
246     int filenames_mode = 0;
247 
248     if (!strcmp(contents_encryption_mode, "software") ||
249         !strcmp(contents_encryption_mode, "aes-256-xts")) {
250         contents_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
251     } else if (!strcmp(contents_encryption_mode, "adiantum")) {
252         contents_mode = FS_ENCRYPTION_MODE_ADIANTUM;
253     } else if (!strcmp(contents_encryption_mode, "ice")) {
254         contents_mode = FS_ENCRYPTION_MODE_PRIVATE;
255     } else {
256         LOG(ERROR) << "Invalid file contents encryption mode: "
257                    << contents_encryption_mode;
258         return -1;
259     }
260 
261     if (!strcmp(filenames_encryption_mode, "aes-256-cts")) {
262         filenames_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
263     } else if (!strcmp(filenames_encryption_mode, "aes-256-heh")) {
264         filenames_mode = FS_ENCRYPTION_MODE_AES_256_HEH;
265     } else if (!strcmp(filenames_encryption_mode, "adiantum")) {
266         filenames_mode = FS_ENCRYPTION_MODE_ADIANTUM;
267     } else {
268         LOG(ERROR) << "Invalid file names encryption mode: "
269                    << filenames_encryption_mode;
270         return -1;
271     }
272 
273     bool is_empty;
274     if (!is_dir_empty(directory, &is_empty)) return -1;
275     if (is_empty) {
276         if (!fscrypt_policy_set(directory, policy, policy_length,
277                                 contents_mode, filenames_mode)) return -1;
278     } else {
279         if (!fscrypt_policy_check(directory, policy, policy_length,
280                                   contents_mode, filenames_mode)) return -1;
281     }
282     return 0;
283 }
284