• 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 "key_control.h"
16 
17 #include <bits/fcntl.h>
18 #include <ctype.h>
19 #include <sys/syscall.h>
20 #include <fcntl.h>
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/ioctl.h>
26 #include <unistd.h>
27 #include <linux/keyctl.h>
28 
29 #include "fscrypt_log.h"
30 #include "fscrypt_sysparam.h"
31 #include "init_utils.h"
32 #include "securec.h"
33 #include "storage_radar_c.h"
34 
KeyCtrlGetKeyringId(key_serial_t id,int create)35 key_serial_t KeyCtrlGetKeyringId(key_serial_t id, int create)
36 {
37     return syscall(__NR_keyctl, KEYCTL_GET_KEYRING_ID, id, create);
38 }
39 
KeyCtrlAddKey(const char * type,const char * description,const key_serial_t ringId)40 key_serial_t KeyCtrlAddKey(const char *type, const char *description,
41     const key_serial_t ringId)
42 {
43     return syscall(__NR_add_key, type, description, NULL, 0, ringId);
44 }
45 
KeyCtrlAddKeyEx(const char * type,const char * description,struct fscrypt_key * fsKey,const key_serial_t ringId)46 key_serial_t KeyCtrlAddKeyEx(const char *type, const char *description,
47     struct fscrypt_key *fsKey, const key_serial_t ringId)
48 {
49     return syscall(__NR_add_key, type, description,
50         (void *)(fsKey), sizeof(struct fscrypt_key),
51         ringId);
52 }
53 
KeyCtrlAddKeySdp(const char * type,const char * description,struct EncryptionKeySdp * fsKey,const key_serial_t ringId)54 key_serial_t KeyCtrlAddKeySdp(const char *type, const char *description,
55                              struct EncryptionKeySdp *fsKey, const key_serial_t ringId)
56 {
57     return syscall(__NR_add_key, type, description,
58                    (void *)(fsKey), sizeof(struct EncryptionKeySdp),
59                    ringId);
60 }
61 
KeyCtrlAddAppAsdpKey(const char * type,const char * description,struct EncryptAsdpKey * fsKey,const key_serial_t ringId)62 key_serial_t KeyCtrlAddAppAsdpKey(const char *type,
63                                   const char *description,
64                                   struct EncryptAsdpKey *fsKey,
65                                   const key_serial_t ringId)
66 {
67     return syscall(__NR_add_key, type, description,
68                    (void *)(fsKey), sizeof(struct EncryptAsdpKey),
69                    ringId);
70 }
71 
KeyCtrlSearch(key_serial_t ringId,const char * type,const char * description,key_serial_t destRingId)72 long KeyCtrlSearch(key_serial_t ringId, const char *type, const char *description,
73     key_serial_t destRingId)
74 {
75     return syscall(__NR_keyctl, KEYCTL_SEARCH, ringId, type,
76         description, destRingId);
77 }
78 
KeyCtrlUnlink(key_serial_t key,key_serial_t keyring)79 long KeyCtrlUnlink(key_serial_t key, key_serial_t keyring)
80 {
81     return syscall(__NR_keyctl, KEYCTL_UNLINK, key, keyring);
82 }
83 
FsIoctl(const char * mnt,unsigned long cmd,void * arg)84 static bool FsIoctl(const char *mnt, unsigned long cmd, void *arg)
85 {
86     char *realPath = realpath(mnt, NULL);
87     if (realPath == NULL) {
88         LOGE("realpath failed");
89         return false;
90     }
91 
92     int fd = open(realPath, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
93     free(realPath);
94     if (fd < 0 && cmd == FS_IOC_SET_ENCRYPTION_POLICY) {
95         RADAR_REPORT(mnt, "fd open failed! ", errno);
96     }
97     if (fd < 0) {
98         LOGE("open %{public}s failed, errno:%{public}d", mnt, errno);
99         return false;
100     }
101     int ret = ioctl(fd, cmd, arg);
102     if (ret != 0 && cmd == FS_IOC_SET_ENCRYPTION_POLICY) {
103         RADAR_REPORT(mnt, "set policy failed! ", errno);
104     }
105     if (ret != 0) {
106         LOGE("ioctl to %{public}s failed, errno:%{public}d", mnt, ret);
107         (void)close(fd);
108         return false;
109     }
110     (void)close(fd);
111     LOGI("success");
112     return true;
113 }
114 
115 #ifdef SUPPORT_FSCRYPT_V2
KeyCtrlInstallKey(const char * mnt,struct fscrypt_add_key_arg * arg)116 bool KeyCtrlInstallKey(const char *mnt, struct fscrypt_add_key_arg *arg)
117 {
118     LOGI("enter");
119     return FsIoctl(mnt, FS_IOC_ADD_ENCRYPTION_KEY, (void *)(arg));
120 }
121 
KeyCtrlRemoveKey(const char * mnt,struct fscrypt_remove_key_arg * arg)122 bool KeyCtrlRemoveKey(const char *mnt, struct fscrypt_remove_key_arg *arg)
123 {
124     LOGI("enter");
125     return FsIoctl(mnt, FS_IOC_REMOVE_ENCRYPTION_KEY, (void *)arg);
126 }
127 
KeyCtrlGetKeyStatus(const char * mnt,struct fscrypt_get_key_status_arg * arg)128 bool KeyCtrlGetKeyStatus(const char *mnt, struct fscrypt_get_key_status_arg *arg)
129 {
130     LOGI("enter");
131     return FsIoctl(mnt, FS_IOC_GET_ENCRYPTION_KEY_STATUS, (void *)(arg));
132 }
133 
KeyCtrlGetPolicyEx(const char * path,struct fscrypt_get_policy_ex_arg * policy)134 bool KeyCtrlGetPolicyEx(const char *path, struct fscrypt_get_policy_ex_arg *policy)
135 {
136     LOGI("enter");
137     return FsIoctl(path, FS_IOC_GET_ENCRYPTION_POLICY_EX, (void *)(policy));
138 }
139 #endif
140 
KeyCtrlSetPolicy(const char * path,union FscryptPolicy * policy)141 bool KeyCtrlSetPolicy(const char *path, union FscryptPolicy *policy)
142 {
143     LOGI("enter");
144     return FsIoctl(path, FS_IOC_SET_ENCRYPTION_POLICY, (void *)(policy));
145 }
146 
KeyCtrlGetPolicy(const char * path,struct fscrypt_policy * policy)147 bool KeyCtrlGetPolicy(const char *path, struct fscrypt_policy *policy)
148 {
149     LOGI("enter");
150     return FsIoctl(path, FS_IOC_GET_ENCRYPTION_POLICY, (void *)(policy));
151 }
152 
CheckKernelFscrypt(const char * mnt)153 static uint8_t CheckKernelFscrypt(const char *mnt)
154 {
155     char *realPath = realpath(mnt, NULL);
156     if (realPath == NULL) {
157         LOGE("realpath failed");
158         return FSCRYPT_INVALID_REALPATH;
159     }
160 
161     int fd = open(realPath, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
162     free(realPath);
163     if (fd < 0) {
164         LOGE("open policy file failed, errno: %{public}d", errno);
165         return FSCRYPT_INVALID_OPEN;
166     }
167 
168 #ifdef SUPPORT_FSCRYPT_V2
169     errno = 0;
170     (void)ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, NULL);
171     (void)close(fd);
172     if (errno == EOPNOTSUPP) {
173         LOGE("Kernel doesn't support fscrypt v1 or v2.");
174         return FSCRYPT_INVALID_NOT_SUPPORT;
175     } else if (errno == ENOTTY || errno == EAGAIN) {
176         LOGE("Kernel doesn't support fscrypt v2, pls use v1.");
177         return FSCRYPT_V1;
178     } else if (errno == EFAULT) {
179         LOGI("Kernel is support fscrypt v2.");
180         return FSCRYPT_V2;
181     }
182     LOGE("Unexpected errno: %{public}d", errno);
183     return FSCRYPT_INVALID_UNEXPECTED;
184 #else
185     (void)close(fd);
186     return FSCRYPT_V1;
187 #endif
188 }
189 
KeyCtrlGetFscryptVersion(const char * mnt)190 uint8_t KeyCtrlGetFscryptVersion(const char *mnt)
191 {
192     uint8_t version = CheckKernelFscrypt(mnt);
193     return version;
194 }
195 
KeyCtrlHasFscryptSyspara(void)196 bool KeyCtrlHasFscryptSyspara(void)
197 {
198     char tmp[POLICY_BUF_SIZE] = { 0 };
199     uint32_t len = POLICY_BUF_SIZE;
200     int ret = GetFscryptParameter(FSCRYPT_POLICY_KEY, "", tmp, &len);
201     if (ret != 0) {
202         LOGE("fscrypt config parameter not set, not enable fscrypt");
203         return false;
204     }
205 
206     return true;
207 }
208 
KeyCtrlLoadVersion(const char * keyPath)209 uint8_t KeyCtrlLoadVersion(const char *keyPath)
210 {
211     (void)keyPath;
212     LOGD("load key control version enter.");
213     return FSCRYPT_V2;
214 }
215