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 "fingerprint_auth_all_in_one_executor_hdi_fuzzer.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 
21 #include "parcel.h"
22 
23 #include "iam_check.h"
24 #include "iam_fuzz_test.h"
25 #include "iam_logger.h"
26 #include "iam_ptr.h"
27 
28 #include "fingerprint_auth_all_in_one_executor_hdi.h"
29 
30 #define LOG_TAG "FINGERPRINT_AUTH_SA"
31 
32 #undef private
33 
34 using namespace std;
35 using namespace OHOS::UserIam::Common;
36 using namespace OHOS::UserIam::UserAuth;
37 
38 namespace OHOS {
39 namespace UserIam {
40 namespace FingerprintAuth {
41 namespace {
42 constexpr uint32_t MAX_VECTOR_LEN = 100;
43 class DummyExecutorProxy : public IAllInOneExecutor {
44 public:
DummyExecutorProxy()45     DummyExecutorProxy() : fuzzParcel_(nullptr)
46     {
47     }
48 
49     virtual ~DummyExecutorProxy() = default;
50 
GetExecutorInfo(ExecutorInfo & executorInfo)51     int32_t GetExecutorInfo(ExecutorInfo &executorInfo)
52     {
53         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
54         FillFuzzHdiExecutorInfo(*fuzzParcel_, executorInfo);
55         return (*fuzzParcel_).ReadInt32();
56     }
57 
OnRegisterFinish(const std::vector<uint64_t> & templateIdList,const std::vector<uint8_t> & frameworkPublicKey,const std::vector<uint8_t> & extraInfo)58     int32_t OnRegisterFinish(const std::vector<uint64_t> &templateIdList,
59         const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo)
60     {
61         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
62         return (*fuzzParcel_).ReadInt32();
63     }
64 
Enroll(uint64_t scheduleId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallback> & callbackObj)65     int32_t Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
66         const sptr<IExecutorCallback> &callbackObj)
67     {
68         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
69         return (*fuzzParcel_).ReadInt32();
70     }
71 
Authenticate(uint64_t scheduleId,const std::vector<uint64_t> & templateIdList,bool endAfterFirstFail,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallback> & callbackObj)72     int32_t Authenticate(uint64_t scheduleId, const std::vector<uint64_t> &templateIdList, bool endAfterFirstFail,
73         const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj)
74     {
75         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
76         return (*fuzzParcel_).ReadInt32();
77     }
78 
Identify(uint64_t scheduleId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallback> & callbackObj)79     int32_t Identify(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
80         const sptr<IExecutorCallback> &callbackObj)
81     {
82         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
83         return (*fuzzParcel_).ReadInt32();
84     }
85 
Delete(const std::vector<uint64_t> & templateIdList)86     int32_t Delete(const std::vector<uint64_t> &templateIdList)
87     {
88         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
89         return (*fuzzParcel_).ReadInt32();
90     }
91 
Cancel(uint64_t scheduleId)92     int32_t Cancel(uint64_t scheduleId)
93     {
94         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
95         return (*fuzzParcel_).ReadInt32();
96     }
97 
SendCommand(int32_t commandId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallback> & callbackObj)98     int32_t SendCommand(int32_t commandId, const std::vector<uint8_t> &extraInfo,
99         const sptr<IExecutorCallback> &callbackObj)
100     {
101         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
102         return (*fuzzParcel_).ReadInt32();
103     }
104 
SendMessage(uint64_t scheduleId,int32_t srcRole,const std::vector<uint8_t> & msg)105     int32_t SendMessage(uint64_t scheduleId, int32_t srcRole, const std::vector<uint8_t> &msg)
106     {
107         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
108         return (*fuzzParcel_).ReadInt32();
109     }
110 
GetProperty(const std::vector<uint64_t> & templateIdList,const std::vector<int32_t> & propertyTypes,Property & property)111     int32_t GetProperty(const std::vector<uint64_t> &templateIdList, const std::vector<int32_t> &propertyTypes,
112         Property &property)
113     {
114         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
115         FillFuzzHdiProperty(*fuzzParcel_, property);
116         return (*fuzzParcel_).ReadInt32();
117     }
118 
SetCachedTemplates(const std::vector<uint64_t> & templateIdList)119     int32_t SetCachedTemplates(const std::vector<uint64_t> &templateIdList)
120     {
121         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
122         return (*fuzzParcel_).ReadInt32();
123     }
124 
RegisterSaCommandCallback(const sptr<ISaCommandCallback> & callbackObj)125     int32_t RegisterSaCommandCallback(const sptr<ISaCommandCallback> &callbackObj)
126     {
127         IF_FALSE_LOGE_AND_RETURN_VAL(fuzzParcel_ != nullptr, 0);
128         callbackObj_ = callbackObj;
129         return (*fuzzParcel_).ReadInt32();
130     }
131 
SetParcel(Parcel & parcel)132     void SetParcel(Parcel &parcel)
133     {
134         fuzzParcel_ = &parcel;
135     }
136 
ClearParcel()137     void ClearParcel()
138     {
139         fuzzParcel_ = nullptr;
140     }
141 
FuzzTriggerSaCommandCallback(Parcel & parcel)142     void FuzzTriggerSaCommandCallback(Parcel &parcel)
143     {
144         if (callbackObj_ == nullptr) {
145             return;
146         }
147 
148         std::vector<SaCommand> commands;
149         FillFuzzSaCommandVector(parcel, commands);
150         callbackObj_->OnSaCommands(commands);
151     }
152 
153 private:
FillFuzzHdiExecutorInfo(Parcel & parcel,ExecutorInfo & executorInfo)154     void FillFuzzHdiExecutorInfo(Parcel &parcel, ExecutorInfo &executorInfo)
155     {
156         executorInfo.sensorId = parcel.ReadUint16();
157         executorInfo.executorMatcher = parcel.ReadUint32();
158         executorInfo.executorRole = static_cast<ExecutorRole>(parcel.ReadInt32());
159         executorInfo.authType = static_cast<AuthType>(parcel.ReadInt32());
160         executorInfo.esl = static_cast<ExecutorSecureLevel>(parcel.ReadInt32());
161         executorInfo.maxTemplateAcl = parcel.ReadInt32();
162         FillFuzzUint8Vector(parcel, executorInfo.publicKey);
163         FillFuzzUint8Vector(parcel, executorInfo.extraInfo);
164         IAM_LOGI("success");
165     }
166 
FillFuzzHdiProperty(Parcel & parcel,Property & property)167     void FillFuzzHdiProperty(Parcel &parcel, Property &property)
168     {
169         property.authSubType = parcel.ReadUint64();
170         property.lockoutDuration = parcel.ReadInt32();
171         property.remainAttempts = parcel.ReadInt32();
172         FillFuzzString(parcel, property.enrollmentProgress);
173         FillFuzzString(parcel, property.sensorInfo);
174 
175         IAM_LOGI("success");
176     }
177 
FillFuzzSaCommand(Parcel & parcel,SaCommand & command)178     void FillFuzzSaCommand(Parcel &parcel, SaCommand &command)
179     {
180         command.id = static_cast<SaCommandId>(parcel.ReadInt32());
181         IAM_LOGI("success");
182     }
183 
FillFuzzSaCommandVector(Parcel & parcel,std::vector<SaCommand> & commands)184     void FillFuzzSaCommandVector(Parcel &parcel, std::vector<SaCommand> &commands)
185     {
186         uint32_t len = parcel.ReadUint32() % MAX_VECTOR_LEN;
187         commands.resize(len);
188         for (uint32_t i = 0; i < len; i++) {
189             FillFuzzSaCommand(parcel, commands[i]);
190         }
191         IAM_LOGI("success");
192     }
193 
194     Parcel *fuzzParcel_;
195     sptr<ISaCommandCallback> callbackObj_ { nullptr };
196 };
197 
198 class DummyExecuteCallback : public UserAuth::IExecuteCallback {
199 public:
200     virtual ~DummyExecuteCallback() = default;
201 
OnResult(ResultCode result,const std::vector<uint8_t> & extraInfo)202     void OnResult(ResultCode result, const std::vector<uint8_t> &extraInfo) override
203     {
204     }
205 
OnResult(ResultCode result)206     void OnResult(ResultCode result) override
207     {
208     }
209 
OnAcquireInfo(int32_t acquire,const std::vector<uint8_t> & extraInfo)210     void OnAcquireInfo(int32_t acquire, const std::vector<uint8_t> &extraInfo) override
211     {
212     }
213 
OnMessage(int destRole,const std::vector<uint8_t> & msg)214     void OnMessage(int destRole, const std::vector<uint8_t> &msg) override
215     {}
216 };
217 
218 auto g_proxy = new (nothrow) DummyExecutorProxy();
219 auto g_hdi = Common::MakeShared<FingerprintAllInOneExecutorHdi>(g_proxy);
220 
FillFuzzExecutorInfo(Parcel & parcel,UserAuth::ExecutorInfo & executorInfo)221 void FillFuzzExecutorInfo(Parcel &parcel, UserAuth::ExecutorInfo &executorInfo)
222 {
223     executorInfo.executorSensorHint = parcel.ReadInt32();
224     executorInfo.authType = static_cast<UserAuth::AuthType>(parcel.ReadInt32());
225     executorInfo.executorRole = static_cast<UserAuth::ExecutorRole>(parcel.ReadInt32());
226     executorInfo.executorMatcher = parcel.ReadInt32();
227     executorInfo.esl = static_cast<UserAuth::ExecutorSecureLevel>(parcel.ReadInt32());
228     FillFuzzUint8Vector(parcel, executorInfo.publicKey);
229     IAM_LOGI("success");
230 }
231 
FillFuzzIExecuteCallback(Parcel & parcel,std::shared_ptr<UserAuth::IExecuteCallback> & callback)232 void FillFuzzIExecuteCallback(Parcel &parcel, std::shared_ptr<UserAuth::IExecuteCallback> &callback)
233 {
234     callback = nullptr;
235     if (parcel.ReadBool()) {
236         callback = MakeShared<DummyExecuteCallback>();
237         if (callback == nullptr) {
238             IAM_LOGE("callback is nullptr");
239         }
240     }
241     IAM_LOGI("success");
242 }
243 
FillFuzzAttributeKeyVector(Parcel & parcel,std::vector<UserAuth::Attributes::AttributeKey> & keys)244 void FillFuzzAttributeKeyVector(Parcel &parcel, std::vector<UserAuth::Attributes::AttributeKey> &keys)
245 {
246     std::vector<uint32_t> vals;
247     FillFuzzUint32Vector(parcel, vals);
248     for (const auto &val : vals) {
249         keys.push_back(static_cast<UserAuth::Attributes::AttributeKey>(val));
250     }
251 
252     IAM_LOGI("success");
253 }
254 
FuzzGetExecutorInfo(Parcel & parcel)255 void FuzzGetExecutorInfo(Parcel &parcel)
256 {
257     IAM_LOGI("begin");
258     UserAuth::ExecutorInfo info;
259     FillFuzzExecutorInfo(parcel, info);
260     g_hdi->GetExecutorInfo(info);
261     IAM_LOGI("end");
262 }
263 
FuzzOnRegisterFinish(Parcel & parcel)264 void FuzzOnRegisterFinish(Parcel &parcel)
265 {
266     IAM_LOGI("begin");
267     std::vector<uint64_t> templateIdList;
268     FillFuzzUint64Vector(parcel, templateIdList);
269     std::vector<uint8_t> frameworkPublicKey;
270     FillFuzzUint8Vector(parcel, frameworkPublicKey);
271     std::vector<uint8_t> extraInfo;
272     FillFuzzUint8Vector(parcel, extraInfo);
273     g_hdi->OnRegisterFinish(templateIdList, frameworkPublicKey, extraInfo);
274     IAM_LOGI("end");
275 }
276 
FuzzEnroll(Parcel & parcel)277 void FuzzEnroll(Parcel &parcel)
278 {
279     IAM_LOGI("begin");
280     uint64_t scheduleId = parcel.ReadUint64();
281     uint32_t tokenId = parcel.ReadUint32();
282     std::vector<uint8_t> extraInfo;
283     FillFuzzUint8Vector(parcel, extraInfo);
284     std::shared_ptr<UserAuth::IExecuteCallback> callbackObj;
285     FillFuzzIExecuteCallback(parcel, callbackObj);
286     g_hdi->Enroll(scheduleId, EnrollParam { tokenId, extraInfo }, callbackObj);
287     IAM_LOGI("end");
288 }
289 
FuzzAuthenticate(Parcel & parcel)290 void FuzzAuthenticate(Parcel &parcel)
291 {
292     IAM_LOGI("begin");
293     uint64_t scheduleId = parcel.ReadUint64();
294     uint32_t tokenId = parcel.ReadUint32();
295     std::vector<uint64_t> templateIdList;
296     FillFuzzUint64Vector(parcel, templateIdList);
297     std::vector<uint8_t> extraInfo;
298     FillFuzzUint8Vector(parcel, extraInfo);
299     std::shared_ptr<UserAuth::IExecuteCallback> callbackObj;
300     FillFuzzIExecuteCallback(parcel, callbackObj);
301     bool endAfterFirstFail = parcel.ReadBool();
302     g_hdi->Authenticate(scheduleId, AuthenticateParam { tokenId, templateIdList, extraInfo, endAfterFirstFail },
303         callbackObj);
304     IAM_LOGI("end");
305 }
306 
FuzzIdentify(Parcel & parcel)307 void FuzzIdentify(Parcel &parcel)
308 {
309     IAM_LOGI("begin");
310     uint64_t scheduleId = parcel.ReadUint64();
311     uint32_t tokenId = parcel.ReadUint32();
312     std::vector<uint8_t> extraInfo;
313     FillFuzzUint8Vector(parcel, extraInfo);
314     std::shared_ptr<UserAuth::IExecuteCallback> callbackObj;
315     FillFuzzIExecuteCallback(parcel, callbackObj);
316     g_hdi->Identify(scheduleId, IdentifyParam { tokenId, extraInfo }, callbackObj);
317     IAM_LOGI("end");
318 }
319 
FuzzDelete(Parcel & parcel)320 void FuzzDelete(Parcel &parcel)
321 {
322     IAM_LOGI("begin");
323     std::vector<uint64_t> templateIdList;
324     FillFuzzUint64Vector(parcel, templateIdList);
325     g_hdi->Delete(templateIdList);
326     IAM_LOGI("end");
327 }
328 
FuzzCancel(Parcel & parcel)329 void FuzzCancel(Parcel &parcel)
330 {
331     IAM_LOGI("begin");
332     uint64_t scheduleId = parcel.ReadUint64();
333     g_hdi->Cancel(scheduleId);
334     IAM_LOGI("end");
335 }
336 
FuzzSendCommand(Parcel & parcel)337 void FuzzSendCommand(Parcel &parcel)
338 {
339     IAM_LOGI("begin");
340     PropertyMode commandId = static_cast<PropertyMode>(parcel.ReadInt32());
341     std::vector<uint8_t> extraInfo;
342     FillFuzzUint8Vector(parcel, extraInfo);
343     std::shared_ptr<UserAuth::IExecuteCallback> callbackObj;
344     FillFuzzIExecuteCallback(parcel, callbackObj);
345     g_hdi->SendCommand(commandId, extraInfo, callbackObj);
346     IAM_LOGI("end");
347 }
348 
FuzzGetProperty(Parcel & parcel)349 void FuzzGetProperty(Parcel &parcel)
350 {
351     IAM_LOGI("begin");
352     std::vector<uint64_t> templateIdList;
353     FillFuzzUint64Vector(parcel, templateIdList);
354     std::vector<UserAuth::Attributes::AttributeKey> keys;
355     FillFuzzAttributeKeyVector(parcel, keys);
356     UserAuth::Property property;
357     g_hdi->GetProperty(templateIdList, keys, property);
358     IAM_LOGI("end");
359 }
360 
FuzzSetCachedTemplates(Parcel & parcel)361 void FuzzSetCachedTemplates(Parcel &parcel)
362 {
363     IAM_LOGI("begin");
364     std::vector<uint64_t> templateIdList;
365     FillFuzzUint64Vector(parcel, templateIdList);
366     g_hdi->SetCachedTemplates(templateIdList);
367     IAM_LOGI("end");
368 }
369 
FuzzSendMessage(Parcel & parcel)370 void FuzzSendMessage(Parcel &parcel)
371 {
372     IAM_LOGI("begin");
373     IAM_LOGI("end");
374 }
375 
FuzzTriggerSaCommandCallback(Parcel & parcel)376 void FuzzTriggerSaCommandCallback(Parcel &parcel)
377 {
378     IAM_LOGI("begin");
379     g_proxy->FuzzTriggerSaCommandCallback(parcel);
380     IAM_LOGI("end");
381 }
382 
SetProxyParcel(Parcel & parcel)383 void SetProxyParcel(Parcel &parcel)
384 {
385     if (g_proxy == nullptr) {
386         IAM_LOGE("g_proxy is nullptr");
387         return;
388     }
389     g_proxy->SetParcel(parcel);
390 }
391 
ClearProxyParcel()392 void ClearProxyParcel()
393 {
394     if (g_proxy == nullptr) {
395         IAM_LOGE("g_proxy is nullptr");
396         return;
397     }
398     g_proxy->ClearParcel();
399 }
400 
401 using FuzzFunc = decltype(FuzzGetExecutorInfo);
402 FuzzFunc *g_fuzzFuncs[] = { FuzzGetExecutorInfo, FuzzOnRegisterFinish, FuzzEnroll, FuzzAuthenticate, FuzzIdentify,
403     FuzzDelete, FuzzCancel, FuzzSendCommand, FuzzGetProperty, FuzzSetCachedTemplates, FuzzTriggerSaCommandCallback,
404     FuzzSendMessage };
405 
FingerprintAuthServiceFuzzTest(const uint8_t * data,size_t size)406 void FingerprintAuthServiceFuzzTest(const uint8_t *data, size_t size)
407 {
408     Parcel parcel;
409     parcel.WriteBuffer(data, size);
410     parcel.RewindRead(0);
411     uint32_t index = parcel.ReadUint32() % (sizeof(g_fuzzFuncs) / sizeof(FuzzFunc *));
412     auto fuzzFunc = g_fuzzFuncs[index];
413     SetProxyParcel(parcel);
414     fuzzFunc(parcel);
415     ClearProxyParcel();
416     return;
417 }
418 } // namespace
419 } // namespace FingerprintAuth
420 } // namespace UserIam
421 } // namespace OHOS
422 
423 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)424 extern "C" int32_t LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
425 {
426     OHOS::UserIam::FingerprintAuth::FingerprintAuthServiceFuzzTest(data, size);
427     return 0;
428 }
429