• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "fscrypt_control.h"
16 
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <stdbool.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 
25 #include "fscrypt_log.h"
26 #include "fscrypt_sysparam.h"
27 #include "init_utils.h"
28 #include "key_control.h"
29 #include "securec.h"
30 
31 #define ARRAY_LEN(array) (sizeof((array)) / sizeof((array)[0]))
32 
33 typedef struct FscrtpyItem_ {
34     char *key;
35     uint8_t value;
36 }FscrtpyItem;
37 
38 typedef struct EncryptPolicy_ {
39     uint8_t version;
40     uint8_t fileName;
41     uint8_t content;
42     uint8_t flags;
43     bool hwWrappedKey;
44 }EncryptPolicy;
45 
46 static EncryptPolicy g_fscryptPolicy = {
47     FSCRYPT_V2,
48     FSCRYPT_MODE_AES_256_CTS,
49     FSCRYPT_MODE_AES_256_XTS,
50     FSCRYPT_POLICY_FLAGS_PAD_32,
51     false
52 };
53 
54 enum FscryptOptins {
55     FSCRYPT_VERSION_NUM = 0,
56     FSCRYPT_FILENAME_MODE,
57     FSCRYPT_CONTENT_MODE,
58     FSCRYPT_OPTIONS_MAX,
59 };
60 
61 static const FscrtpyItem ALL_VERSION[] = {
62     {"1", FSCRYPT_V1},
63     {"2", FSCRYPT_V2},
64 };
65 
66 static const FscrtpyItem FILENAME_MODES[] = {
67     {"aes-256-cts", FSCRYPT_MODE_AES_256_CTS},
68 };
69 
70 static const FscrtpyItem CONTENTS_MODES[] = {
71     {"aes-256-xts", FSCRYPT_MODE_AES_256_XTS},
72 };
73 
74 static bool g_fscryptEnabled = false;
75 static bool g_fscryptInited = false;
76 
77 static const char *GLOBAL_FSCRYPT_DIR[] = {
78     "/data/app/el1/bundle/public",
79     "/data/service/el1/public",
80     "/data/chipset/el1/public",
81 };
82 
83 static const char *DEVICE_EL1_DIR = "/data/service/el0/storage_daemon/sd";
84 static const char *PATH_KEYDESC = "/key_desc";
85 #ifdef SUPPORT_FSCRYPT_V2
86 static const char *PATH_KEYID = "/key_id";
87 #endif
88 
IsSupportedPolicyKey(const char * key,const FscrtpyItem * items,size_t len)89 static bool IsSupportedPolicyKey(const char *key,
90                                  const FscrtpyItem *items,
91                                  size_t len)
92 {
93     for (size_t i = 0 ; i < len; i++) {
94         if (strncmp(key, items[i].key, strlen(items[i].key)) == 0) {
95             return true;
96         }
97     }
98     return false;
99 }
100 
IsSupportedPolicy(const char * policy,enum FscryptOptins number)101 static bool IsSupportedPolicy(const char *policy,
102                               enum FscryptOptins number)
103 {
104     if ((number >= FSCRYPT_OPTIONS_MAX) || (!policy)) {
105         return false;
106     }
107 
108     switch (number) {
109         case FSCRYPT_VERSION_NUM:
110             return IsSupportedPolicyKey(policy, ALL_VERSION,
111                 ARRAY_LEN(ALL_VERSION));
112         case FSCRYPT_FILENAME_MODE:
113             return IsSupportedPolicyKey(policy, FILENAME_MODES,
114                 ARRAY_LEN(FILENAME_MODES));
115         case FSCRYPT_CONTENT_MODE:
116             return IsSupportedPolicyKey(policy, CONTENTS_MODES,
117                 ARRAY_LEN(CONTENTS_MODES));
118         default:
119             return false;
120     }
121     return false;
122 }
123 
FscryptSetSysparam(const char * policy)124 int FscryptSetSysparam(const char *policy)
125 {
126     if (!policy) {
127         return -EINVAL;
128     }
129 
130     char *tmp = strdup(policy);
131     if (!tmp) {
132         FSCRYPT_LOGE("No memory for policy option");
133         return -ENOMEM;
134     }
135     int optNums = 0;
136     char **options = SplitStringExt(tmp, ":", &optNums, FSCRYPT_OPTIONS_MAX);
137     free(tmp);
138     if (!options) {
139         return -ENOMEM;
140     }
141     if (optNums != FSCRYPT_OPTIONS_MAX) {
142         FSCRYPT_LOGE("Mount fscrypt option setting error, not enabled crypto!");
143         FreeStringVector(options, optNums);
144         return -EFAULT;
145     }
146 
147     // check supported policy
148     for (enum FscryptOptins i = FSCRYPT_VERSION_NUM; i < FSCRYPT_OPTIONS_MAX; i++) {
149         char *temp = options[i];
150         if (!IsSupportedPolicy(temp, i)) {
151             FSCRYPT_LOGE("Not supported policy, %s", temp);
152             FreeStringVector(options, optNums);
153             return -ENOTSUP;
154         }
155     }
156     FreeStringVector(options, optNums);
157 
158     int ret = SetFscryptParameter(FSCRYPT_POLICY_KEY, policy);
159     if (ret < 0) {
160         FSCRYPT_LOGE("Set fscrypt system parameter failed %d", ret);
161         return ret;
162     }
163     g_fscryptEnabled = true;
164     g_fscryptInited = false; // need to re-init
165 
166     return 0;
167 }
168 
169 #ifdef USER_CRYPTO_MANAGER
PraseOnePloicyValue(uint8_t * value,const char * key,const FscrtpyItem * table,size_t numbers)170 static void PraseOnePloicyValue(uint8_t *value, const char *key,
171                                 const FscrtpyItem *table, size_t numbers)
172 {
173     for (size_t i = 0; i < numbers; i++) {
174         size_t len = strlen(table[i].key);
175         if (strncmp(key, table[i].key, len) == 0 &&
176             strlen(key) == len) {
177             *value = table[i].value;
178             return;
179         }
180     }
181     FSCRYPT_LOGE("Have not found value for the key!");
182 }
183 #endif
184 
InitFscryptPolicy(void)185 int InitFscryptPolicy(void)
186 {
187 #ifdef USER_CRYPTO_MANAGER
188     if (g_fscryptInited) {
189         FSCRYPT_LOGI("Have been init");
190         return 0;
191     }
192     char policy[POLICY_BUF_SIZE];
193     uint32_t len = POLICY_BUF_SIZE - 1;
194     int ret = GetFscryptParameter(FSCRYPT_POLICY_KEY, "", policy, &len);
195     if (ret != 0) {
196         FSCRYPT_LOGI("Get fscrypt policy failed");
197         return -ENOTSUP;
198     }
199     int count = 0;
200     char **option = SplitStringExt(policy, ":", &count, FSCRYPT_OPTIONS_MAX);
201     if (!option) {
202         FSCRYPT_LOGE("Fscrypt setting error");
203         return -ENOTSUP;
204     }
205     if (count != FSCRYPT_OPTIONS_MAX) {
206         FSCRYPT_LOGE("Fscrypt policy count error");
207         FreeStringVector(option, count);
208         return -ENOTSUP;
209     }
210 
211     PraseOnePloicyValue(&g_fscryptPolicy.version, option[FSCRYPT_VERSION_NUM],
212         ALL_VERSION, ARRAY_LEN(ALL_VERSION));
213     PraseOnePloicyValue(&g_fscryptPolicy.fileName, option[FSCRYPT_FILENAME_MODE],
214         FILENAME_MODES, ARRAY_LEN(FILENAME_MODES));
215     PraseOnePloicyValue(&g_fscryptPolicy.content, option[FSCRYPT_CONTENT_MODE],
216         CONTENTS_MODES, ARRAY_LEN(CONTENTS_MODES));
217 
218     FreeStringVector(option, count);
219     g_fscryptInited = true;
220     FSCRYPT_LOGI("Fscrypt policy init success");
221 #endif
222 
223     return 0;
224 }
225 
226 /*
227  * Splic full path, Caller need to free *buf after using
228  * if return success.
229  *
230  * @path: base key path
231  * @name: fscrypt file, so as /key_id
232  * @buf: splic result if return 0
233  */
SpliceKeyPath(const char * path,size_t pathLen,const char * name,size_t nameLen,char ** buf)234 static int SpliceKeyPath(const char *path, size_t pathLen,
235                          const char *name, size_t nameLen,
236                          char **buf)
237 {
238     FSCRYPT_LOGI("key path %s, name %s", path, name);
239     *buf = NULL;
240     size_t bufMax = pathLen + nameLen + 1;
241     char *tmpBuf = (char *)malloc(bufMax);
242     if (!tmpBuf) {
243         FSCRYPT_LOGE("No memory for fscrypt v1 path buffer");
244         return -ENOMEM;
245     }
246     tmpBuf[0] = '\0';
247 
248     int ret = strncat_s(tmpBuf, bufMax, path, pathLen);
249     if (ret != 0) {
250         free(tmpBuf);
251         FSCRYPT_LOGE("splic previous path error");
252         return ret;
253     }
254     ret = strncat_s(tmpBuf, bufMax, name, nameLen);
255     if (ret != 0) {
256         free(tmpBuf);
257         FSCRYPT_LOGE("splic later path error");
258         return ret;
259     }
260     *buf = tmpBuf;
261 
262     return 0;
263 }
264 
ReadKeyFile(const char * path,char * buf,size_t len)265 static int ReadKeyFile(const char *path, char *buf, size_t len)
266 {
267     if (!path || !buf) {
268         FSCRYPT_LOGE("path or buf is null");
269         return -EINVAL;
270     }
271     struct stat st = {0};
272     if (stat(path, &st) != 0) {
273         FSCRYPT_LOGE("stat file failed");
274         return -EFAULT;
275     }
276     if ((size_t)st.st_size != len) {
277         FSCRYPT_LOGE("target file size is not equal to buf len");
278         return -EFAULT;
279     }
280     char *realPath = realpath(path, NULL);
281     if (realPath == NULL) {
282         FSCRYPT_LOGE("realpath failed");
283         return -EFAULT;
284     }
285 
286     int fd = open(realPath, O_RDONLY);
287     free(realPath);
288     if (fd < 0) {
289         FSCRYPT_LOGE("key file read open failed");
290         return -EFAULT;
291     }
292     if (read(fd, buf, len) != (ssize_t)len) {
293         FSCRYPT_LOGE("bad file content");
294         (void)close(fd);
295         return -EBADF;
296     }
297     (void)close(fd);
298 
299     return 0;
300 }
301 
SetPolicyLegacy(const char * keyDescPath,const char * toEncrypt,union FscryptPolicy * arg)302 static int SetPolicyLegacy(const char *keyDescPath,
303                            const char *toEncrypt,
304                            union FscryptPolicy *arg)
305 {
306     char keyDesc[FSCRYPT_KEY_DESCRIPTOR_SIZE] = {0};
307     int ret = ReadKeyFile(keyDescPath, keyDesc, FSCRYPT_KEY_DESCRIPTOR_SIZE);
308     if (ret != 0) {
309         return ret;
310     }
311     arg->v1.version = FSCRYPT_POLICY_V1;
312     ret = memcpy_s(arg->v1.master_key_descriptor,
313         FSCRYPT_KEY_DESCRIPTOR_SIZE, keyDesc, FSCRYPT_KEY_DESCRIPTOR_SIZE);
314     if (ret != 0) {
315         FSCRYPT_LOGE("memcpy_s copy failed");
316         return ret;
317     }
318     if (!KeyCtrlSetPolicy(toEncrypt, arg)) {
319         FSCRYPT_LOGE("Set Policy v1 failed");
320         return -EFAULT;
321     }
322     return 0;
323 }
324 
325 #ifdef SUPPORT_FSCRYPT_V2
SetPolicyV2(const char * keyIdPath,const char * toEncrypt,union FscryptPolicy * arg)326 static int SetPolicyV2(const char *keyIdPath,
327                        const char *toEncrypt,
328                        union FscryptPolicy *arg)
329 {
330     char keyId[FSCRYPT_KEY_IDENTIFIER_SIZE] = {0};
331     int ret = ReadKeyFile(keyIdPath, keyId, FSCRYPT_KEY_IDENTIFIER_SIZE);
332     if (ret != 0) {
333         return ret;
334     }
335     arg->v2.version = FSCRYPT_POLICY_V2;
336     ret = memcpy_s(arg->v2.master_key_identifier,
337         FSCRYPT_KEY_IDENTIFIER_SIZE, keyId, FSCRYPT_KEY_IDENTIFIER_SIZE);
338     if (ret != 0) {
339         FSCRYPT_LOGE("memcpy_s copy failed");
340         return ret;
341     }
342     if (!KeyCtrlSetPolicy(toEncrypt, arg)) {
343         FSCRYPT_LOGE("Set Policy v2 failed");
344         return -EFAULT;
345     }
346     return 0;
347 }
348 #endif
349 
LoadAndSetPolicy(const char * keyDir,const char * dir)350 int LoadAndSetPolicy(const char *keyDir, const char *dir)
351 {
352     if (!keyDir || !dir) {
353         FSCRYPT_LOGE("set policy parameters is null");
354         return -EINVAL;
355     }
356     int ret = InitFscryptPolicy();
357     if (ret != 0) {
358         FSCRYPT_LOGE("Get fscrypt policy error %d", ret);
359         return ret;
360     }
361 
362     union FscryptPolicy arg;
363     (void)memset_s(&arg, sizeof(arg), 0, sizeof(arg));
364     arg.v1.filenames_encryption_mode = g_fscryptPolicy.fileName;
365     arg.v1.contents_encryption_mode = g_fscryptPolicy.content;
366     arg.v1.flags = g_fscryptPolicy.flags;
367 
368     char *pathBuf = NULL;
369     ret = -ENOTSUP;
370 
371     uint8_t fscryptVer = KeyCtrlLoadVersion(keyDir);
372     if (fscryptVer == FSCRYPT_V1) {
373         ret = SpliceKeyPath(keyDir, strlen(keyDir), PATH_KEYDESC,
374             strlen(PATH_KEYDESC), &pathBuf);
375         if (ret != 0) {
376             FSCRYPT_LOGE("path splice error");
377             return ret;
378         }
379         ret = SetPolicyLegacy(pathBuf, dir, &arg);
380 #ifdef SUPPORT_FSCRYPT_V2
381     } else if (fscryptVer == FSCRYPT_V2) {
382         ret = SpliceKeyPath(keyDir, strlen(keyDir), PATH_KEYID,
383             strlen(PATH_KEYID), &pathBuf);
384         if (ret != 0) {
385             FSCRYPT_LOGE("path splice error");
386             return ret;
387         }
388         ret = SetPolicyV2(pathBuf, dir, &arg);
389 #endif
390     }
391     if (pathBuf != NULL) {
392         free(pathBuf);
393     }
394 
395     return ret;
396 }
397 
SetGlobalEl1DirPolicy(const char * dir)398 int SetGlobalEl1DirPolicy(const char *dir)
399 {
400     if (!g_fscryptEnabled) {
401         FSCRYPT_LOGI("Fscrypt have not enabled");
402         return 0;
403     }
404     for (size_t i = 0; i < ARRAY_LEN(GLOBAL_FSCRYPT_DIR); i++) {
405         size_t tmpLen = strlen(GLOBAL_FSCRYPT_DIR[i]);
406         if ((strncmp(dir, GLOBAL_FSCRYPT_DIR[i], tmpLen) == 0) &&
407             (strlen(dir) == tmpLen)) {
408             return LoadAndSetPolicy(DEVICE_EL1_DIR, dir);
409         }
410     }
411     return 0;
412 }
413 
GetFscryptVersionFromPolicy(void)414 uint8_t GetFscryptVersionFromPolicy(void)
415 {
416     return g_fscryptPolicy.version;
417 }
418