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, &paramSet) != 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, &paramSetBlob) != 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(&paramSet);
351         return false;
352     }
353 
354     OHOS::MessageParcel context;
355     (void)ipcServiceApi(&paramSetBlob, &outData, reinterpret_cast<struct CmContext *>(&context));
356 
357     CmFree(myData);
358     CmFreeParamSet(&paramSet);
359     return true;
360 }
361 }
362