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