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 
16 #include <unistd.h>
17 #include <limits.h>
18 #include <securec.h>
19 #include "device_attest_oem_file.h"
20 
21 #define MAX_ATTEST_MALLOC_BUFF_SIZE 1024
22 
OEMGenFilePath(const char* dirPath, const char* fileName)23 char* OEMGenFilePath(const char* dirPath, const char* fileName)
24 {
25     if (dirPath == NULL || fileName == NULL) {
26         return NULL;
27     }
28     if ((strlen(dirPath) >= MAX_ATTEST_MALLOC_BUFF_SIZE) ||\
29         (strlen(fileName) >= MAX_ATTEST_MALLOC_BUFF_SIZE) ||\
30         (strlen(dirPath) + strlen(fileName)) >= MAX_ATTEST_MALLOC_BUFF_SIZE) {
31         return NULL;
32     }
33     uint32_t filePathLen = strlen(dirPath) + 1 + strlen(fileName) + 1;
34     if (filePathLen > PATH_MAX) {
35         return NULL;
36     }
37     char* filePath = (char *)malloc(filePathLen);
38     if (filePath == NULL) {
39         return NULL;
40     }
41     (void)memset_s(filePath, filePathLen, 0, filePathLen);
42     if (sprintf_s(filePath, filePathLen, "%s%s%s", dirPath, "/", fileName) < 0) {
43         free(filePath);
44         return NULL;
45     }
46     return filePath;
47 }
48 
OEMGetFileSize(const char* path, const char* fileName, uint32_t* result)49 int32_t OEMGetFileSize(const char* path, const char* fileName, uint32_t* result)
50 {
51     if (path == NULL || fileName == NULL || result == NULL) {
52         return DEVICE_ATTEST_OEM_ERR;
53     }
54 
55     char* filePath = OEMGenFilePath(path, fileName);
56     if (filePath == NULL) {
57         return DEVICE_ATTEST_OEM_ERR;
58     }
59 
60     char* formatPath = realpath(filePath, NULL);
61     if (formatPath == NULL) {
62         free(filePath);
63         return DEVICE_ATTEST_OEM_ERR;
64     }
65 
66     FILE* fp = fopen(formatPath, "r");
67     if (fp == NULL) {
68         free(formatPath);
69         free(filePath);
70         return DEVICE_ATTEST_OEM_ERR;
71     }
72     if (fseek(fp, 0, SEEK_END) < 0) {
73         free(formatPath);
74         free(filePath);
75         (void)fclose(fp);
76         return DEVICE_ATTEST_OEM_ERR;
77     }
78     *result = ftell(fp);
79     free(formatPath);
80     free(filePath);
81     (void)fclose(fp);
82     return DEVICE_ATTEST_OEM_OK;
83 }
84 
OEMWriteFile(const char* path, const char* fileName, const char* data, uint32_t dataLen)85 int32_t OEMWriteFile(const char* path, const char* fileName, const char* data, uint32_t dataLen)
86 {
87     if (path == NULL || fileName == NULL || data == NULL || dataLen == 0) {
88         return DEVICE_ATTEST_OEM_ERR;
89     }
90 
91     char* filePath = OEMGenFilePath(path, fileName);
92     if (filePath == NULL) {
93         return DEVICE_ATTEST_OEM_ERR;
94     }
95 
96     char* formatPath = realpath(filePath, NULL);
97     free(filePath);
98     if (formatPath == NULL) {
99         return DEVICE_ATTEST_OEM_ERR;
100     }
101 
102     FILE* fp = fopen(formatPath, "wb+");
103     if (fp == NULL) {
104         free(formatPath);
105         return DEVICE_ATTEST_OEM_ERR;
106     }
107     int32_t ret = DEVICE_ATTEST_OEM_OK;
108     do {
109         if (fwrite(data, dataLen, 1, fp) != 1) {
110             ret = DEVICE_ATTEST_OEM_ERR;
111             break;
112         }
113         if (fflush(fp) != DEVICE_ATTEST_OEM_OK) {
114             ret = DEVICE_ATTEST_OEM_ERR;
115             break;
116         }
117         int fd = fileno(fp);
118         if (fsync(fd) != DEVICE_ATTEST_OEM_OK) {
119             ret = DEVICE_ATTEST_OEM_ERR;
120             break;
121         }
122     } while (0);
123     free(formatPath);
124     (void)fclose(fp);
125     return ret;
126 }
127 
OEMReadFile(const char* path, const char* fileName, char* buffer, uint32_t bufferLen)128 int32_t OEMReadFile(const char* path, const char* fileName, char* buffer, uint32_t bufferLen)
129 {
130     if (path == NULL || fileName == NULL || buffer == NULL || bufferLen == 0) {
131         return DEVICE_ATTEST_OEM_ERR;
132     }
133 
134     uint32_t fileSize = 0;
135     if (OEMGetFileSize(path, fileName, &fileSize) != 0 || fileSize > bufferLen) {
136         return DEVICE_ATTEST_OEM_ERR;
137     }
138 
139     char* filePath = OEMGenFilePath(path, fileName);
140     if (filePath == NULL) {
141         return DEVICE_ATTEST_OEM_ERR;
142     }
143 
144     char* formatPath = realpath(filePath, NULL);
145     free(filePath);
146     if (formatPath == NULL) {
147         return DEVICE_ATTEST_OEM_ERR;
148     }
149 
150     FILE* fp = fopen(formatPath, "rb");
151     if (fp == NULL) {
152         free(formatPath);
153         return DEVICE_ATTEST_OEM_ERR;
154     }
155     if (fread(buffer, fileSize, 1, fp) != 1) {
156         free(formatPath);
157         (void)fclose(fp);
158         return DEVICE_ATTEST_OEM_ERR;
159     }
160     free(formatPath);
161     (void)fclose(fp);
162     return DEVICE_ATTEST_OEM_OK;
163 }
164 
OEMCreateFileImpl(char* formatPath, const char* fileName)165 static int32_t OEMCreateFileImpl(char* formatPath, const char* fileName)
166 {
167     uint32_t realPathLen = strlen(formatPath) + 1 + strlen(fileName) + 1;
168     if (realPathLen > PATH_MAX) {
169         free(formatPath);
170         return DEVICE_ATTEST_OEM_ERR;
171     }
172     char* realPath = (char *)malloc(realPathLen);
173     if (realPath == NULL) {
174         free(formatPath);
175         return DEVICE_ATTEST_OEM_ERR;
176     }
177     (void)memset_s(realPath, realPathLen, 0, realPathLen);
178     if (sprintf_s(realPath, realPathLen, "%s%s%s", formatPath, "/", fileName) < 0) {
179         free(formatPath);
180         free(realPath);
181         return DEVICE_ATTEST_OEM_ERR;
182     }
183     free(formatPath);
184 
185     FILE* fp = fopen(realPath, "w");
186     if (fp == NULL) {
187         free(realPath);
188         return DEVICE_ATTEST_OEM_ERR;
189     }
190     free(realPath);
191     int32_t ret = DEVICE_ATTEST_OEM_OK;
192     do {
193         if (fflush(fp) != DEVICE_ATTEST_OEM_OK) {
194             ret = DEVICE_ATTEST_OEM_ERR;
195             break;
196         }
197         int fd = fileno(fp);
198         if (fsync(fd) != DEVICE_ATTEST_OEM_OK) {
199             ret = DEVICE_ATTEST_OEM_ERR;
200             break;
201         }
202     } while (0);
203     (void)fclose(fp);
204     return ret;
205 }
206 
OEMCreateFile(const char* path, const char* fileName)207 int32_t OEMCreateFile(const char* path, const char* fileName)
208 {
209     if (path == NULL || fileName == NULL) {
210         return DEVICE_ATTEST_OEM_ERR;
211     }
212     char* formatPath = realpath(path, NULL);
213     if (formatPath == NULL) {
214         return DEVICE_ATTEST_OEM_ERR;
215     }
216     if ((strlen(formatPath) >= MAX_ATTEST_MALLOC_BUFF_SIZE) ||\
217         (strlen(fileName) >= MAX_ATTEST_MALLOC_BUFF_SIZE) ||\
218         (strlen(formatPath) + strlen(fileName)) >= MAX_ATTEST_MALLOC_BUFF_SIZE) {
219         free(formatPath);
220         return DEVICE_ATTEST_OEM_ERR;
221     }
222     return OEMCreateFileImpl(formatPath, fileName);
223 }