1e656c62eSopenharmony_ci/*
2e656c62eSopenharmony_ci * Copyright (C) 2023 Huawei Technologies Co., Ltd.
3e656c62eSopenharmony_ci * Licensed under the Mulan PSL v2.
4e656c62eSopenharmony_ci * You can use this software according to the terms and conditions of the Mulan PSL v2.
5e656c62eSopenharmony_ci * You may obtain a copy of Mulan PSL v2 at:
6e656c62eSopenharmony_ci *     http://license.coscl.org.cn/MulanPSL2
7e656c62eSopenharmony_ci * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8e656c62eSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9e656c62eSopenharmony_ci * PURPOSE.
10e656c62eSopenharmony_ci * See the Mulan PSL v2 for more details.
11e656c62eSopenharmony_ci */
12e656c62eSopenharmony_ci
13e656c62eSopenharmony_ci#include "tcu_authentication.h"
14e656c62eSopenharmony_ci#include <unistd.h>
15e656c62eSopenharmony_ci#include <errno.h> /* for errno */
16e656c62eSopenharmony_ci#include <fcntl.h>
17e656c62eSopenharmony_ci#include <sys/types.h> /* for open close */
18e656c62eSopenharmony_ci#include <sys/ioctl.h> /* for ioctl */
19e656c62eSopenharmony_ci#include <sys/stat.h> /* for stat */
20e656c62eSopenharmony_ci#include <linux/limits.h>
21e656c62eSopenharmony_ci#include "securec.h"
22e656c62eSopenharmony_ci#include "tee_log.h"
23e656c62eSopenharmony_ci#include "tc_ns_client.h"
24e656c62eSopenharmony_ci#include "tee_client_type.h"
25e656c62eSopenharmony_ci
26e656c62eSopenharmony_ci#ifdef LOG_TAG
27e656c62eSopenharmony_ci#undef LOG_TAG
28e656c62eSopenharmony_ci#endif
29e656c62eSopenharmony_ci#define LOG_TAG            "tcu_authentication"
30e656c62eSopenharmony_ci#define HASH_FILE_MAX_SIZE (16 * 1024)
31e656c62eSopenharmony_ci#define ERR_SIZE           (-1)
32e656c62eSopenharmony_ci#define XML_HEADER         4
33e656c62eSopenharmony_ci#define MAX_HASHFILE_PATHLEN 256
34e656c62eSopenharmony_ci
35e656c62eSopenharmony_cistatic const char *g_vendorCaHashFileList[] = {
36e656c62eSopenharmony_ci    "/vendor/etc/native_packages.xml",
37e656c62eSopenharmony_ci    "/vendor/root/res/native_packages.xml",
38e656c62eSopenharmony_ci};
39e656c62eSopenharmony_ci
40e656c62eSopenharmony_cistatic const char *g_systemCaHashFileList[] = {
41e656c62eSopenharmony_ci    "/system/etc/native_packages.xml",
42e656c62eSopenharmony_ci};
43e656c62eSopenharmony_ci
44e656c62eSopenharmony_cistatic const char **GetCaHashFileList(uint8_t *num, uint8_t hash_type)
45e656c62eSopenharmony_ci{
46e656c62eSopenharmony_ci    if (num == NULL) {
47e656c62eSopenharmony_ci        tloge("input parameter error\n");
48e656c62eSopenharmony_ci        return NULL;
49e656c62eSopenharmony_ci    }
50e656c62eSopenharmony_ci
51e656c62eSopenharmony_ci    if (hash_type == HASH_TYPE_SYSTEM) {
52e656c62eSopenharmony_ci        *num = sizeof(g_systemCaHashFileList) / sizeof(intptr_t);
53e656c62eSopenharmony_ci        return g_systemCaHashFileList;
54e656c62eSopenharmony_ci    } else {
55e656c62eSopenharmony_ci        *num = sizeof(g_vendorCaHashFileList) / sizeof(intptr_t);
56e656c62eSopenharmony_ci        return g_vendorCaHashFileList;
57e656c62eSopenharmony_ci    }
58e656c62eSopenharmony_ci}
59e656c62eSopenharmony_ci
60e656c62eSopenharmony_cistatic int IsNotValidFname(const char *path)
61e656c62eSopenharmony_ci{
62e656c62eSopenharmony_ci    if (path == NULL) {
63e656c62eSopenharmony_ci        tloge("filename is invalid ...\n");
64e656c62eSopenharmony_ci        return 1;
65e656c62eSopenharmony_ci    }
66e656c62eSopenharmony_ci
67e656c62eSopenharmony_ci    /* filter the .. dir in the pname: */
68e656c62eSopenharmony_ci    if (strstr(path, "..") != NULL) {
69e656c62eSopenharmony_ci        tloge("filename should not include .. dir\n");
70e656c62eSopenharmony_ci        return 1;
71e656c62eSopenharmony_ci    }
72e656c62eSopenharmony_ci
73e656c62eSopenharmony_ci    return 0;
74e656c62eSopenharmony_ci}
75e656c62eSopenharmony_ci
76e656c62eSopenharmony_cistatic int GetFileSize(const char *path, int *realSize)
77e656c62eSopenharmony_ci{
78e656c62eSopenharmony_ci    FILE *fp = NULL;
79e656c62eSopenharmony_ci    int ret;
80e656c62eSopenharmony_ci    int fileSize                = -1;
81e656c62eSopenharmony_ci    int xmlHeader               = 0;
82e656c62eSopenharmony_ci    char realPath[PATH_MAX + 1] = { 0 };
83e656c62eSopenharmony_ci
84e656c62eSopenharmony_ci    bool paramInvlid = ((path == NULL) || (IsNotValidFname(path) != 0) || (strlen(path) > PATH_MAX) ||
85e656c62eSopenharmony_ci                        (realpath(path, realPath) == NULL));
86e656c62eSopenharmony_ci    if (paramInvlid) {
87e656c62eSopenharmony_ci        return fileSize;
88e656c62eSopenharmony_ci    }
89e656c62eSopenharmony_ci
90e656c62eSopenharmony_ci    fp = fopen(realPath, "r");
91e656c62eSopenharmony_ci    if (fp == NULL) {
92e656c62eSopenharmony_ci        return fileSize;
93e656c62eSopenharmony_ci    }
94e656c62eSopenharmony_ci
95e656c62eSopenharmony_ci    ret = fseek(fp, 0L, SEEK_END);
96e656c62eSopenharmony_ci    if (ret < 0) {
97e656c62eSopenharmony_ci        fclose(fp);
98e656c62eSopenharmony_ci        fp = NULL;
99e656c62eSopenharmony_ci        return fileSize;
100e656c62eSopenharmony_ci    }
101e656c62eSopenharmony_ci
102e656c62eSopenharmony_ci    fileSize = (int)ftell(fp);
103e656c62eSopenharmony_ci
104e656c62eSopenharmony_ci    ret = fseek(fp, 0L, SEEK_SET);
105e656c62eSopenharmony_ci    if (ret < 0 || fileSize < XML_HEADER) {
106e656c62eSopenharmony_ci        fclose(fp);
107e656c62eSopenharmony_ci        fp = NULL;
108e656c62eSopenharmony_ci        return ERR_SIZE;
109e656c62eSopenharmony_ci    }
110e656c62eSopenharmony_ci    int len = (int)fread(&xmlHeader, 1, sizeof(int), fp);
111e656c62eSopenharmony_ci    if (len != sizeof(int) || xmlHeader < fileSize) {
112e656c62eSopenharmony_ci        tloge("size read is invalid\n");
113e656c62eSopenharmony_ci        fclose(fp);
114e656c62eSopenharmony_ci        fp = NULL;
115e656c62eSopenharmony_ci        return ERR_SIZE;
116e656c62eSopenharmony_ci    }
117e656c62eSopenharmony_ci
118e656c62eSopenharmony_ci    (void)fclose(fp);
119e656c62eSopenharmony_ci    fp = NULL;
120e656c62eSopenharmony_ci    *realSize = fileSize;
121e656c62eSopenharmony_ci    return xmlHeader;
122e656c62eSopenharmony_ci}
123e656c62eSopenharmony_ci
124e656c62eSopenharmony_cistatic int GetFileInfo(int bufLen, uint8_t *buffer, const char *path)
125e656c62eSopenharmony_ci{
126e656c62eSopenharmony_ci    FILE *fp = NULL;
127e656c62eSopenharmony_ci    int fileSize;
128e656c62eSopenharmony_ci    char realPath[PATH_MAX + 1] = { 0 };
129e656c62eSopenharmony_ci
130e656c62eSopenharmony_ci    bool paramInvlid = ((buffer == NULL) || (path == NULL) || (IsNotValidFname(path) != 0) ||
131e656c62eSopenharmony_ci                        (strlen(path) > PATH_MAX) || (realpath(path, realPath) == NULL) ||
132e656c62eSopenharmony_ci                        (bufLen == 0));
133e656c62eSopenharmony_ci    if (paramInvlid) {
134e656c62eSopenharmony_ci        return -1;
135e656c62eSopenharmony_ci    }
136e656c62eSopenharmony_ci
137e656c62eSopenharmony_ci    fp = fopen(realPath, "rb");
138e656c62eSopenharmony_ci    if (fp == NULL) {
139e656c62eSopenharmony_ci        tloge("open file failed\n");
140e656c62eSopenharmony_ci        return -1;
141e656c62eSopenharmony_ci    }
142e656c62eSopenharmony_ci
143e656c62eSopenharmony_ci    fileSize = (int)fread(buffer, sizeof(char), (unsigned int)bufLen, fp);
144e656c62eSopenharmony_ci    if (fileSize != bufLen) {
145e656c62eSopenharmony_ci        tloge("read file read number:%d\n", fileSize);
146e656c62eSopenharmony_ci        fclose(fp);
147e656c62eSopenharmony_ci        fp = NULL;
148e656c62eSopenharmony_ci        return -1;
149e656c62eSopenharmony_ci    }
150e656c62eSopenharmony_ci
151e656c62eSopenharmony_ci    (void)fclose(fp);
152e656c62eSopenharmony_ci    fp = NULL;
153e656c62eSopenharmony_ci    return 0;
154e656c62eSopenharmony_ci}
155e656c62eSopenharmony_ci
156e656c62eSopenharmony_cistatic uint8_t *InitTempBuf(int bufLen)
157e656c62eSopenharmony_ci{
158e656c62eSopenharmony_ci    errno_t ret;
159e656c62eSopenharmony_ci    uint8_t *buffer = NULL;
160e656c62eSopenharmony_ci
161e656c62eSopenharmony_ci    bool variablesCheck = ((bufLen <= 0) || (bufLen > HASH_FILE_MAX_SIZE));
162e656c62eSopenharmony_ci    if (variablesCheck) {
163e656c62eSopenharmony_ci        tloge("wrong buflen\n");
164e656c62eSopenharmony_ci        return buffer;
165e656c62eSopenharmony_ci    }
166e656c62eSopenharmony_ci
167e656c62eSopenharmony_ci    buffer = (uint8_t *)malloc((unsigned int)bufLen);
168e656c62eSopenharmony_ci    if (buffer == NULL) {
169e656c62eSopenharmony_ci        tloge("malloc failed!\n");
170e656c62eSopenharmony_ci        return buffer;
171e656c62eSopenharmony_ci    }
172e656c62eSopenharmony_ci
173e656c62eSopenharmony_ci    ret = memset_s(buffer, (unsigned int)bufLen, 0, (unsigned int)bufLen);
174e656c62eSopenharmony_ci    if (ret != EOK) {
175e656c62eSopenharmony_ci        tloge("memset failed!\n");
176e656c62eSopenharmony_ci        free(buffer);
177e656c62eSopenharmony_ci        buffer = NULL;
178e656c62eSopenharmony_ci        return buffer;
179e656c62eSopenharmony_ci    }
180e656c62eSopenharmony_ci
181e656c62eSopenharmony_ci    return buffer;
182e656c62eSopenharmony_ci}
183e656c62eSopenharmony_ci
184e656c62eSopenharmony_cistatic uint8_t *ReadXmlFile(const char *xmlFile)
185e656c62eSopenharmony_ci{
186e656c62eSopenharmony_ci    int ret;
187e656c62eSopenharmony_ci    int bufLen;
188e656c62eSopenharmony_ci    uint8_t *buffer = NULL;
189e656c62eSopenharmony_ci    int realSize = 0;
190e656c62eSopenharmony_ci
191e656c62eSopenharmony_ci    bufLen = GetFileSize(xmlFile, &realSize);
192e656c62eSopenharmony_ci    buffer = InitTempBuf(bufLen);
193e656c62eSopenharmony_ci    if (buffer == NULL) {
194e656c62eSopenharmony_ci        tloge("init temp buffer failed\n");
195e656c62eSopenharmony_ci        return buffer;
196e656c62eSopenharmony_ci    }
197e656c62eSopenharmony_ci
198e656c62eSopenharmony_ci    ret = GetFileInfo(realSize, buffer, xmlFile);
199e656c62eSopenharmony_ci    if (ret != 0) {
200e656c62eSopenharmony_ci        tloge("get xml file info failed\n");
201e656c62eSopenharmony_ci        free(buffer);
202e656c62eSopenharmony_ci        buffer = NULL;
203e656c62eSopenharmony_ci        return buffer;
204e656c62eSopenharmony_ci    }
205e656c62eSopenharmony_ci
206e656c62eSopenharmony_ci    return buffer;
207e656c62eSopenharmony_ci}
208e656c62eSopenharmony_ci
209e656c62eSopenharmony_cistatic int TeeSetNativeCaHash(const char *xmlFlie)
210e656c62eSopenharmony_ci{
211e656c62eSopenharmony_ci    int ret;
212e656c62eSopenharmony_ci    int fd          = -1;
213e656c62eSopenharmony_ci    uint8_t *buffer = NULL;
214e656c62eSopenharmony_ci
215e656c62eSopenharmony_ci    buffer = ReadXmlFile(xmlFlie);
216e656c62eSopenharmony_ci    if (buffer == NULL) {
217e656c62eSopenharmony_ci        tloge("read xml file failed\n");
218e656c62eSopenharmony_ci        return fd;
219e656c62eSopenharmony_ci    }
220e656c62eSopenharmony_ci
221e656c62eSopenharmony_ci    fd = open(TC_PRIVATE_DEV_NAME, O_RDWR);
222e656c62eSopenharmony_ci    if (fd < 0) {
223e656c62eSopenharmony_ci        tloge("Failed to open dev node: %d\n", errno);
224e656c62eSopenharmony_ci        free(buffer);
225e656c62eSopenharmony_ci        buffer = NULL;
226e656c62eSopenharmony_ci        return -1;
227e656c62eSopenharmony_ci    }
228e656c62eSopenharmony_ci    ret = ioctl(fd, (int)(TC_NS_CLIENT_IOCTL_SET_NATIVE_IDENTITY), buffer);
229e656c62eSopenharmony_ci    if (ret != 0) {
230e656c62eSopenharmony_ci        tloge("ioctl fail %d\n", ret);
231e656c62eSopenharmony_ci    }
232e656c62eSopenharmony_ci
233e656c62eSopenharmony_ci    free(buffer);
234e656c62eSopenharmony_ci    buffer = NULL;
235e656c62eSopenharmony_ci    close(fd);
236e656c62eSopenharmony_ci    fd = -1;
237e656c62eSopenharmony_ci    return ret;
238e656c62eSopenharmony_ci}
239e656c62eSopenharmony_ci
240e656c62eSopenharmony_cistatic bool IsFileExist(const char *name)
241e656c62eSopenharmony_ci{
242e656c62eSopenharmony_ci    struct stat statbuf;
243e656c62eSopenharmony_ci
244e656c62eSopenharmony_ci    if (name == NULL) {
245e656c62eSopenharmony_ci        return false;
246e656c62eSopenharmony_ci    }
247e656c62eSopenharmony_ci    if (stat(name, &statbuf) != 0) {
248e656c62eSopenharmony_ci        if (errno == ENOENT) { /* file not exist */
249e656c62eSopenharmony_ci            tlogi("file not exist: %s\n", name);
250e656c62eSopenharmony_ci            return false;
251e656c62eSopenharmony_ci        }
252e656c62eSopenharmony_ci        return true;
253e656c62eSopenharmony_ci    }
254e656c62eSopenharmony_ci
255e656c62eSopenharmony_ci    return true;
256e656c62eSopenharmony_ci}
257e656c62eSopenharmony_ci
258e656c62eSopenharmony_ciint TcuAuthentication(uint8_t hash_type)
259e656c62eSopenharmony_ci{
260e656c62eSopenharmony_ci    uint8_t listLen;
261e656c62eSopenharmony_ci    const char **hashFileList = GetCaHashFileList(&listLen, hash_type);
262e656c62eSopenharmony_ci    if (hashFileList == NULL) {
263e656c62eSopenharmony_ci        tloge("get hashFileList failed\n");
264e656c62eSopenharmony_ci        return -1;
265e656c62eSopenharmony_ci    }
266e656c62eSopenharmony_ci    if (listLen == 0) {
267e656c62eSopenharmony_ci        tloge("list num is 0, please set hashfile\n");
268e656c62eSopenharmony_ci        return -1;
269e656c62eSopenharmony_ci    }
270e656c62eSopenharmony_ci    static int gHashXmlSetted;
271e656c62eSopenharmony_ci    uint8_t count = 0;
272e656c62eSopenharmony_ci    if (gHashXmlSetted == 0) {
273e656c62eSopenharmony_ci        for (uint8_t index = 0; index < listLen; index++) {
274e656c62eSopenharmony_ci            if (hashFileList[index] == NULL) {
275e656c62eSopenharmony_ci                tloge("get hashFile failed, index is %d\n", index);
276e656c62eSopenharmony_ci                continue;
277e656c62eSopenharmony_ci            }
278e656c62eSopenharmony_ci            if (!IsFileExist(hashFileList[index])) {
279e656c62eSopenharmony_ci                continue;
280e656c62eSopenharmony_ci            }
281e656c62eSopenharmony_ci
282e656c62eSopenharmony_ci            int setRet = TeeSetNativeCaHash(hashFileList[index]);
283e656c62eSopenharmony_ci            if (setRet != 0) {
284e656c62eSopenharmony_ci                tloge("hashfile read failed, index is %d\n", index);
285e656c62eSopenharmony_ci                continue;
286e656c62eSopenharmony_ci            }
287e656c62eSopenharmony_ci            count++;
288e656c62eSopenharmony_ci        }
289e656c62eSopenharmony_ci    }
290e656c62eSopenharmony_ci
291e656c62eSopenharmony_ci    if (count == listLen) {
292e656c62eSopenharmony_ci        gHashXmlSetted = 1;
293e656c62eSopenharmony_ci        return 0;
294e656c62eSopenharmony_ci    }
295e656c62eSopenharmony_ci
296e656c62eSopenharmony_ci    return -1;
297e656c62eSopenharmony_ci}