1 /*
2 * Copyright (c) 2022-2023 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 "cm_fuzz_test_common.h"
17
18 #include "cm_ipc_client_serialization.h"
19 #include "message_parcel.h"
20
21 namespace CmFuzzTest {
GetUintFromBuffer(uint8_t * srcData,uint32_t * remSize,uint32_t * offset,uint32_t * outVal)22 bool GetUintFromBuffer(uint8_t *srcData, uint32_t *remSize, uint32_t *offset, uint32_t *outVal)
23 {
24 if (*remSize < sizeof(uint32_t)) {
25 return false;
26 }
27
28 (void)memcpy_s(outVal, sizeof(uint32_t), srcData + *offset, sizeof(uint32_t));
29 *remSize -= sizeof(uint32_t);
30 *offset += sizeof(uint32_t);
31
32 return true;
33 }
34
GetCmBlobFromBuffer(uint8_t * srcData,uint32_t * remSize,uint32_t * offset,struct CmBlob * outBlob)35 bool GetCmBlobFromBuffer(uint8_t *srcData, uint32_t *remSize, uint32_t *offset, struct CmBlob *outBlob)
36 {
37 if (GetUintFromBuffer(srcData, remSize, offset, &(outBlob->size)) != true) {
38 return false;
39 }
40
41 if (*remSize < outBlob->size) {
42 return false;
43 }
44 outBlob->data = srcData + *offset;
45 *remSize -= outBlob->size;
46 *offset += outBlob->size;
47
48 return true;
49 }
50
GetCertListFromBuffer(uint8_t * srcData,uint32_t * remSize,uint32_t * offset,struct CertList * outList)51 bool GetCertListFromBuffer(uint8_t *srcData, uint32_t *remSize, uint32_t *offset, struct CertList *outList)
52 {
53 if (GetUintFromBuffer(srcData, remSize, offset, &(outList->certsCount)) != true) {
54 return false;
55 }
56
57 if (outList->certsCount > (*remSize / sizeof(struct CertAbstract))) {
58 return false;
59 }
60 outList->certAbstract = reinterpret_cast<struct CertAbstract *>(srcData + *offset);
61
62 return true;
63 }
64
GetCertInfoFromBuffer(uint8_t * srcData,uint32_t * remSize,uint32_t * offset,struct CertInfo * outInfo)65 bool GetCertInfoFromBuffer(uint8_t *srcData, uint32_t *remSize, uint32_t *offset, struct CertInfo *outInfo)
66 {
67 if (*remSize < sizeof(struct CertInfo)) {
68 return false;
69 }
70
71 outInfo = reinterpret_cast<struct CertInfo *>(srcData + *offset);
72 *remSize -= sizeof(struct CertInfo);
73 *offset += sizeof(struct CertInfo);
74
75 if (*remSize < outInfo->certInfo.size) {
76 return false;
77 }
78
79 outInfo->certInfo.data = const_cast<uint8_t *>(srcData + *offset);
80 return true;
81 }
82
CopyMyData(const uint8_t * data,const size_t size,const uint32_t minSize,uint8_t ** myData)83 bool CopyMyData(const uint8_t *data, const size_t size, const uint32_t minSize, uint8_t **myData)
84 {
85 if (data == nullptr|| static_cast<uint32_t>(size) < minSize) {
86 return false;
87 }
88
89 uint8_t *tempData = static_cast<uint8_t *>(CmMalloc(sizeof(uint8_t) * size));
90 if (tempData == nullptr) {
91 return false;
92 }
93 (void)memcpy_s(tempData, size, data, size);
94
95 *myData = tempData;
96 return true;
97 }
98
99 constexpr uint32_t PARAM_COUNT_ONE = 1;
100 constexpr uint32_t PARAM_COUNT_TWO = 2;
101 constexpr uint32_t PARAM_COUNT_THREE = 3;
102 constexpr uint32_t PARAM_COUNT_FOUR = 4;
103
104 struct CmFuzzerCodeParams {
105 CertManagerInterfaceCode code;
106 uint32_t paramCnt;
107 struct CmParam params[PARAM_COUNT_FOUR];
108 };
109
110 constexpr struct CmFuzzerCodeParams g_codeParams[] = {
111 { CM_MSG_GET_CERTIFICATE_LIST,
112 PARAM_COUNT_ONE,
113 {
114 { .tag = CM_TAG_PARAM0_UINT32, .uint32Param = 0 }
115 }
116 },
117 { CM_MSG_GET_CERTIFICATE_INFO,
118 PARAM_COUNT_TWO,
119 {
120 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
121 { .tag = CM_TAG_PARAM0_UINT32, .uint32Param = 0 },
122 }
123 },
124 { CM_MSG_SET_CERTIFICATE_STATUS,
125 PARAM_COUNT_THREE,
126 {
127 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
128 { .tag = CM_TAG_PARAM0_UINT32, .uint32Param = 0 },
129 { .tag = CM_TAG_PARAM1_UINT32, .uint32Param = 0 },
130 }
131 },
132 { CM_MSG_INSTALL_APP_CERTIFICATE,
133 PARAM_COUNT_FOUR,
134 {
135 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
136 { .tag = CM_TAG_PARAM1_BUFFER, .blob = { 0, nullptr } },
137 { .tag = CM_TAG_PARAM2_BUFFER, .blob = { 0, nullptr } },
138 { .tag = CM_TAG_PARAM3_UINT32, .uint32Param = 0 },
139 }
140 },
141 { CM_MSG_UNINSTALL_APP_CERTIFICATE,
142 PARAM_COUNT_TWO,
143 {
144 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
145 { .tag = CM_TAG_PARAM0_UINT32, .uint32Param = 0 },
146 }
147 },
148 { CM_MSG_UNINSTALL_ALL_APP_CERTIFICATE,
149 0,
150 {
151 }
152 },
153 { CM_MSG_GET_APP_CERTIFICATE_LIST,
154 PARAM_COUNT_ONE,
155 {
156 { .tag = CM_TAG_PARAM0_UINT32, .uint32Param = 0 },
157 }
158 },
159 { CM_MSG_GET_APP_CERTIFICATE,
160 PARAM_COUNT_TWO,
161 {
162 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
163 { .tag = CM_TAG_PARAM0_UINT32, .uint32Param = 0 },
164 }
165 },
166 { CM_MSG_GRANT_APP_CERT,
167 PARAM_COUNT_TWO,
168 {
169 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
170 { .tag = CM_TAG_PARAM1_UINT32, .uint32Param = 0 },
171 }
172 },
173 { CM_MSG_GET_AUTHED_LIST,
174 PARAM_COUNT_ONE,
175 {
176 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
177 }
178 },
179 { CM_MSG_CHECK_IS_AUTHED_APP,
180 PARAM_COUNT_ONE,
181 {
182 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
183 }
184 },
185 { CM_MSG_REMOVE_GRANT_APP,
186 PARAM_COUNT_TWO,
187 {
188 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
189 { .tag = CM_TAG_PARAM1_UINT32, .uint32Param = 0 },
190 }
191 },
192 { CM_MSG_INIT,
193 PARAM_COUNT_TWO,
194 {
195 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
196 { .tag = CM_TAG_PARAM1_BUFFER, .blob = { 0, nullptr } },
197 }
198 },
199 { CM_MSG_UPDATE,
200 PARAM_COUNT_TWO,
201 {
202 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
203 { .tag = CM_TAG_PARAM1_BUFFER, .blob = { 0, nullptr } },
204 }
205 },
206 { CM_MSG_FINISH,
207 PARAM_COUNT_TWO,
208 {
209 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
210 { .tag = CM_TAG_PARAM1_BUFFER, .blob = { 0, nullptr } },
211 }
212 },
213 { CM_MSG_ABORT,
214 PARAM_COUNT_ONE,
215 {
216 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
217 }
218 },
219 { CM_MSG_GET_USER_CERTIFICATE_LIST,
220 PARAM_COUNT_ONE,
221 {
222 { .tag = CM_TAG_PARAM0_UINT32, .uint32Param = 0 },
223 }
224 },
225 { CM_MSG_GET_USER_CERTIFICATE_INFO,
226 PARAM_COUNT_TWO,
227 {
228 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
229 { .tag = CM_TAG_PARAM0_UINT32, .uint32Param = 0 },
230 }
231 },
232 { CM_MSG_SET_USER_CERTIFICATE_STATUS,
233 PARAM_COUNT_THREE,
234 {
235 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
236 { .tag = CM_TAG_PARAM0_UINT32, .uint32Param = 0 },
237 { .tag = CM_TAG_PARAM1_UINT32, .uint32Param = 0 },
238 }
239 },
240 { CM_MSG_INSTALL_USER_CERTIFICATE,
241 PARAM_COUNT_TWO,
242 {
243 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
244 { .tag = CM_TAG_PARAM1_BUFFER, .blob = { 0, nullptr } },
245 }
246 },
247 { CM_MSG_UNINSTALL_USER_CERTIFICATE,
248 PARAM_COUNT_ONE,
249 {
250 { .tag = CM_TAG_PARAM0_BUFFER, .blob = { 0, nullptr } },
251 }
252 },
253 { CM_MSG_UNINSTALL_ALL_USER_CERTIFICATE,
254 0,
255 {
256 }
257 },
258 };
259
ConstructParamSet(uint8_t * srcData,uint32_t * remainSize,uint32_t * offset,CertManagerInterfaceCode code,struct CmParamSet ** paramSetOut)260 bool ConstructParamSet(uint8_t *srcData, uint32_t *remainSize,
261 uint32_t *offset, CertManagerInterfaceCode code, struct CmParamSet **paramSetOut)
262 {
263 struct CmParam params[PARAM_COUNT_FOUR] = {};
264 uint32_t paramCnt = 0;
265 for (uint32_t i = 0; i < (sizeof(g_codeParams) / sizeof(g_codeParams[0])); ++i) {
266 if (code == g_codeParams[i].code) {
267 (void)memcpy_s(params, (sizeof(struct CmParam) * g_codeParams[i].paramCnt),
268 g_codeParams[i].params, (sizeof(struct CmParam) * g_codeParams[i].paramCnt));
269 paramCnt = g_codeParams[i].paramCnt;
270 break;
271 }
272 }
273
274 for (uint32_t i = 0; i < paramCnt; ++i) {
275 switch (GetTagType(static_cast<enum CmTag>(params[i].tag))) {
276 case CM_TAG_TYPE_BYTES:
277 if (!GetCmBlobFromBuffer(srcData, remainSize, offset, &(params[i].blob))) {
278 return false;
279 }
280 break;
281 case CM_TAG_TYPE_UINT:
282 if (!GetUintFromBuffer(srcData, remainSize, offset, &(params[i].uint32Param))) {
283 return false;
284 }
285 break;
286 case CM_TAG_TYPE_BOOL:
287 uint32_t tmp;
288 if (!GetUintFromBuffer(srcData, remainSize, offset, &tmp)) {
289 return false;
290 }
291 params[i].boolParam = (tmp % i == 0 ? true : false);
292 break;
293 default:
294 break;
295 }
296 }
297
298 if (CmParamsToParamSet(params, paramCnt, paramSetOut) != CM_SUCCESS) {
299 return false;
300 }
301
302 return true;
303 }
304
IpcServiceApiFuzzerTest(const uint8_t * data,const size_t size,CertManagerInterfaceCode code,bool isParamsetToBlob,void (* ipcServiceApi)(const struct CmBlob *,struct CmBlob *,const struct CmContext *))305 bool IpcServiceApiFuzzerTest(const uint8_t *data, const size_t size, CertManagerInterfaceCode code,
306 bool isParamsetToBlob, void (*ipcServiceApi)(const struct CmBlob *, struct CmBlob *, const struct CmContext *))
307 {
308 uint32_t minSize = sizeof(struct CmBlob) + sizeof(struct CmBlob);
309 uint8_t *myData = nullptr;
310 if (!CopyMyData(data, size, minSize, &myData)) {
311 return false;
312 }
313
314 uint32_t remSize = static_cast<uint32_t>(size);
315 uint32_t offset = 0;
316
317 struct CmBlob paramSetBlob = { 0, nullptr };
318 struct CmParamSet *paramSet = nullptr;
319 if (isParamsetToBlob) {
320 if (ConstructParamSet(myData, &remSize, &offset, code, ¶mSet) != true) {
321 CmFree(myData);
322 return false;
323 }
324 paramSetBlob = { paramSet->paramSetSize, reinterpret_cast<uint8_t *>(paramSet) };
325 } else {
326 if (GetCmBlobFromBuffer(myData, &remSize, &offset, ¶mSetBlob) != true) {
327 CmFree(myData);
328 return false;
329 }
330 }
331
332 struct CmBlob outData = { 0, nullptr };
333 if (GetCmBlobFromBuffer(myData, &remSize, &offset, &outData) != true) {
334 CmFree(myData);
335 CmFreeParamSet(¶mSet);
336 return false;
337 }
338
339 OHOS::MessageParcel context;
340 (void)ipcServiceApi(¶mSetBlob, &outData, reinterpret_cast<struct CmContext *>(&context));
341
342 CmFree(myData);
343 CmFreeParamSet(¶mSet);
344 return true;
345 }
346 }
347