• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
16 #include "hdf_security.h"
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <inttypes.h>
20 #include <openssl/rand.h>
21 #include <openssl/sha.h>
22 #include <string.h>
23 #include <sys/ioctl.h>
24 #include <sys/time.h>
25 #include <unistd.h>
26 #include "hcs_tree_if.h"
27 #include "hdf_base.h"
28 #include "hdf_log.h"
29 #include "hdf_sec.h"
30 #include "pal_if.h"
31 #include "securec.h"
32 
33 #define HDF_LOG_TAG hdf_security
34 #define HDF_SECURE_PATH "/dev/hdf_secure"
35 #define HDF_SEC_PERM_ELEM_NAME "permission"
36 #define HDF_SEC_HOST_NAME "hostName"
37 #define MAX_RANDOM_BYTE_LEN 8
38 #define RAND_OPS_SUCCESS 1
39 #define MAX_SEED_LEN 64
40 #define HDF_TRANSFORM_STEP 2
41 #define HDF_SECURE_INVALID_PERM 0
42 #define HDF_SECURE_SET_ALL_ID 0
43 #define HDF_SECURE_SET_CUR_ID 1
44 #define HDF_SECURE_DEL_CUR_ID 2
45 
46 #define BITS_PER_LONG 64
47 #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
48 #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
49 
50 const static char *g_hdfSecStrArray[PAL_MAX_TYPE] = {
51     [PAL_I2C_TYPE] = "i2c",
52     [PAL_SPI_TYPE] = "spi",
53     [PAL_GPIO_TYPE] = "gpio",
54     [PAL_PINCTRL_TYPE] = "pinctl",
55     [PAL_CLOCK_TYPE] = "clock",
56     [PAL_REGULATOR_TYPE] = "regulator",
57     [PAL_MIPI_TYPE] = "mipi",
58     [PAL_UART_TYPE] = "uart",
59     [PAL_SDIO_TYPE] = "sdio",
60     [PAL_MDIO_TYPE] = "mdio",
61     [PAL_APB_TYPE] = "apb",
62     [PAL_PCIE_TYPE] = "pcie",
63     [PAL_PCM_TYPE] = "pcm",
64     [PAL_I2S_TYPE] = "i2s",
65     [PAL_PWM_TYPE] = "pwm",
66     [PAL_DMA_TYPE] = "dma",
67     [PAL_EFUSE_TYPE] = "efuse",
68     [PAL_FLASH_TYPE] = "flash",
69     [PAL_EMMC_TYPE] = "emmc",
70     [PAL_RTC_TYPE] = "rtc",
71     [PAL_ADC_TYPE] = "adc",
72     [PAL_WDT_TYPE] = "wdt",
73     [PAL_I3C_TYPE] = "i3c",
74 };
75 
76 static Map g_indexMap;
77 
HdfSecGetHashMap()78 Map *HdfSecGetHashMap()
79 {
80     static Map hdfHashMap = { 0 };
81     if (hdfHashMap.nodeSize == 0) {
82         HDF_LOGI("Init hdfHashMap");
83         MapInit(&hdfHashMap);
84     }
85     return &hdfHashMap;
86 }
87 
InitStrToIndexMap(void)88 static void InitStrToIndexMap(void)
89 {
90     MapInit(&g_indexMap);
91     for (int i = 0; i < PAL_MAX_TYPE; ++i) {
92         MapSet(&g_indexMap, g_hdfSecStrArray[i], &i, sizeof(int *));
93     }
94 }
95 
HdfSetBit(uint32_t nr,volatile uint64_t * addr)96 static void HdfSetBit(uint32_t nr, volatile uint64_t *addr)
97 {
98     unsigned long mask = BIT_MASK(nr);
99     unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
100     *p |= mask;
101 }
102 
HdfGetRandom(int numBytes,uint8_t * random)103 static int32_t HdfGetRandom(int numBytes, uint8_t *random)
104 {
105     if (RAND_bytes(random, numBytes) != RAND_OPS_SUCCESS) {
106         HDF_LOGE("%{public}s: RAND_bytes failed", __FUNCTION__);
107         return HDF_FAILURE;
108     }
109     return HDF_SUCCESS;
110 }
111 
HdfCalculatePerms(const char * permStr,volatile uint64_t * perms)112 static void HdfCalculatePerms(const char *permStr, volatile uint64_t *perms)
113 {
114     uint32_t *result = NULL;
115     result = (uint32_t *)MapGet(&g_indexMap, permStr);
116     if (result == NULL) {
117         HDF_LOGE("%{public}s: %{public}s is not exist in map", __FUNCTION__, permStr);
118         return;
119     }
120     HdfSetBit(*result, perms);
121 }
122 
HdfSecCheckParameters(const char * id)123 static int32_t HdfSecCheckParameters(const char *id)
124 {
125     if (id == NULL) {
126         HDF_LOGE("HdfSecCheckParameters failed, id is null");
127         return HDF_FAILURE;
128     }
129     uint32_t len = (uint32_t)strlen(id);
130     if (len >= (ID_MAX_SIZE - 1)) {
131         HDF_LOGE("HdfSecCheckParameters failed, id length is %{public}u", len);
132         return HDF_FAILURE;
133     }
134     return HDF_SUCCESS;
135 }
136 
HdfUpdateSecurityId(const char * id,uint64_t perms,int32_t isSetCurrentSecId)137 static int32_t HdfUpdateSecurityId(const char *id, uint64_t perms, int32_t isSetCurrentSecId)
138 {
139     if (HdfSecCheckParameters(id) != HDF_SUCCESS) {
140         HDF_LOGE("%{public}s check id failed", __FUNCTION__);
141         return HDF_FAILURE;
142     }
143     struct SecInfo secInfo = {
144         .secId = { 0 },
145         .secMap = { 0 }
146     };
147     int32_t ret = strncpy_s(secInfo.secId, ID_MAX_SIZE, id, ID_MAX_SIZE - 1);
148     if (ret != EOK) {
149         HDF_LOGE("%{public}s strncpy_s id failed", __FUNCTION__);
150         return HDF_FAILURE;
151     }
152     secInfo.secMap[0] = perms;
153 
154     char path[PATH_MAX + 1] = { 0 };
155     if (realpath(HDF_SECURE_PATH, path) == NULL) {
156         HDF_LOGE("file %{public}s is invalid", HDF_SECURE_PATH);
157         return HDF_FAILURE;
158     }
159     int32_t fd = open(path, O_WRONLY);
160     if (fd < 0) {
161         HDF_LOGE("open %{public}s failed, errno is %{public}d", HDF_SECURE_PATH, errno);
162         return HDF_FAILURE;
163     }
164 
165     if (isSetCurrentSecId == 0) {
166         ret = ioctl(fd, HDF_SECURE_SET_INFO, &secInfo);
167     } else if (isSetCurrentSecId == 1) {
168         ret = ioctl(fd, HDF_SECURE_SET_CURRENT_ID, &secInfo);
169     } else {
170         ret = ioctl(fd, HDF_SECURE_DELETE_INFO, &secInfo);
171     }
172 
173     close(fd);
174     fd = -1;
175     if (ret != 0) {
176         HDF_LOGE("%{public}s ioctl error, ret is %{public}d", __FUNCTION__, ret);
177         return HDF_FAILURE;
178     }
179     return HDF_SUCCESS;
180 }
181 
HdfRegisterSecurityId(const char * id,const uint64_t perm)182 static int32_t HdfRegisterSecurityId(const char *id, const uint64_t perm)
183 {
184     return HdfUpdateSecurityId(id, perm, HDF_SECURE_SET_ALL_ID);
185 }
186 
HdfRegisterAllDevSecId(const struct DeviceResourceNode * hostRoot)187 int32_t HdfRegisterAllDevSecId(const struct DeviceResourceNode *hostRoot)
188 {
189     if (hostRoot == NULL) {
190         HDF_LOGE("device_node linked list completed");
191         return HDF_FAILURE;
192     }
193 
194     uint64_t random = 0;
195     int32_t ret = HdfGetRandom(MAX_RANDOM_BYTE_LEN, (uint8_t *)&random);
196     if (ret != HDF_SUCCESS) {
197         HDF_LOGE("%{public}s HdfGetRandom failed", __FUNCTION__);
198         return HDF_FAILURE;
199     }
200 
201     InitStrToIndexMap();
202 
203     struct DeviceResourceNode *driverRoot = hostRoot->child;
204     const char *permStr = NULL;
205     volatile uint64_t perms = HDF_SECURE_INVALID_PERM;
206     while (driverRoot != NULL) {
207         const struct DeviceResourceNode *deviceRoot = driverRoot->child;
208         while (deviceRoot != NULL) {
209             int32_t permNums = HcsGetElemNum(deviceRoot, HDF_SEC_PERM_ELEM_NAME);
210             HDF_LOGD("name is %{public}s, permNums is %{public}d", deviceRoot->name, permNums);
211             for (int i = 0; i < permNums; ++i) {
212                 HcsGetStringArrayElem(deviceRoot, HDF_SEC_PERM_ELEM_NAME, i, &permStr, NULL);
213                 HdfCalculatePerms(permStr, &perms);
214             }
215             deviceRoot = deviceRoot->sibling;
216         }
217         driverRoot = driverRoot->sibling;
218     }
219     if (perms != HDF_SECURE_INVALID_PERM) {
220         const char *hostName = NULL;
221         HcsGetString(hostRoot, HDF_SEC_HOST_NAME, &hostName, NULL);
222         ret = HdfRegisterSecurityId(hostName, perms);
223         if (ret != HDF_SUCCESS) {
224             HDF_LOGE("HdfCreateSecurityId failed for %{public}s", hostRoot->name);
225         }
226         perms = HDF_SECURE_INVALID_PERM;
227     }
228     return HDF_SUCCESS;
229 }
230 
HdfSetCurrentHostSecurity(const char * hostName,int32_t procId)231 int32_t HdfSetCurrentHostSecurity(const char *hostName, int32_t procId)
232 {
233     return HdfUpdateSecurityId(hostName, (uint64_t)procId, HDF_SECURE_SET_CUR_ID);
234 }
235 
HdfDelSecurity(const char * hostName)236 void HdfDelSecurity(const char *hostName)
237 {
238     if (hostName == NULL) {
239         return;
240     }
241     int32_t ret = HdfUpdateSecurityId(hostName, 0, HDF_SECURE_DEL_CUR_ID);
242     if (ret != HDF_SUCCESS) {
243         HDF_LOGE("%{public}s delete %{public}s security failed", __func__, hostName);
244     }
245 }
246