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