1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (C) 2022-2023 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "coauth.h"
17094332d3Sopenharmony_ci
18094332d3Sopenharmony_ci#include "securec.h"
19094332d3Sopenharmony_ci
20094332d3Sopenharmony_ci#include "adaptor_algorithm.h"
21094332d3Sopenharmony_ci#include "adaptor_log.h"
22094332d3Sopenharmony_ci#include "adaptor_memory.h"
23094332d3Sopenharmony_ci#include "pool.h"
24094332d3Sopenharmony_ci
25094332d3Sopenharmony_ci#ifdef IAM_TEST_ENABLE
26094332d3Sopenharmony_ci#define IAM_STATIC
27094332d3Sopenharmony_ci#else
28094332d3Sopenharmony_ci#define IAM_STATIC static
29094332d3Sopenharmony_ci#endif
30094332d3Sopenharmony_ci
31094332d3Sopenharmony_ci// Used to cache the ongoing coAuth scheduling.
32094332d3Sopenharmony_ciIAM_STATIC LinkedList *g_scheduleList = NULL;
33094332d3Sopenharmony_ci
34094332d3Sopenharmony_ciIAM_STATIC bool IsCoAuthInit(void)
35094332d3Sopenharmony_ci{
36094332d3Sopenharmony_ci    return g_scheduleList != NULL;
37094332d3Sopenharmony_ci}
38094332d3Sopenharmony_ci
39094332d3Sopenharmony_civoid DestroyScheduleNode(void *data)
40094332d3Sopenharmony_ci{
41094332d3Sopenharmony_ci    if (data == NULL) {
42094332d3Sopenharmony_ci        LOG_ERROR("get null data");
43094332d3Sopenharmony_ci        return;
44094332d3Sopenharmony_ci    }
45094332d3Sopenharmony_ci    CoAuthSchedule *schedule = (CoAuthSchedule *)data;
46094332d3Sopenharmony_ci    if (schedule->templateIds.data != NULL) {
47094332d3Sopenharmony_ci        Free(schedule->templateIds.data);
48094332d3Sopenharmony_ci        schedule->templateIds.data = NULL;
49094332d3Sopenharmony_ci    }
50094332d3Sopenharmony_ci    Free(schedule);
51094332d3Sopenharmony_ci}
52094332d3Sopenharmony_ci
53094332d3Sopenharmony_ciCoAuthSchedule *CopyCoAuthSchedule(const CoAuthSchedule *coAuthSchedule)
54094332d3Sopenharmony_ci{
55094332d3Sopenharmony_ci    if (coAuthSchedule == NULL || !IsTemplateArraysValid(&(coAuthSchedule->templateIds))) {
56094332d3Sopenharmony_ci        LOG_ERROR("coAuthSchedule is invalid");
57094332d3Sopenharmony_ci        return NULL;
58094332d3Sopenharmony_ci    }
59094332d3Sopenharmony_ci    CoAuthSchedule *schedule = (CoAuthSchedule *)Malloc(sizeof(CoAuthSchedule));
60094332d3Sopenharmony_ci    if (schedule == NULL) {
61094332d3Sopenharmony_ci        LOG_ERROR("schedule is null");
62094332d3Sopenharmony_ci        return NULL;
63094332d3Sopenharmony_ci    }
64094332d3Sopenharmony_ci    if (memcpy_s(schedule, sizeof(CoAuthSchedule), coAuthSchedule, sizeof(CoAuthSchedule)) != EOK) {
65094332d3Sopenharmony_ci        LOG_ERROR("copy schedule failed");
66094332d3Sopenharmony_ci        Free(schedule);
67094332d3Sopenharmony_ci        return NULL;
68094332d3Sopenharmony_ci    }
69094332d3Sopenharmony_ci    schedule->templateIds.data = NULL;
70094332d3Sopenharmony_ci    schedule->templateIds.len = 0;
71094332d3Sopenharmony_ci    ResultCode ret = CopyTemplateArrays(&(coAuthSchedule->templateIds), &(schedule->templateIds));
72094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
73094332d3Sopenharmony_ci        LOG_ERROR("copy templateIds failed");
74094332d3Sopenharmony_ci        Free(schedule);
75094332d3Sopenharmony_ci        return NULL;
76094332d3Sopenharmony_ci    }
77094332d3Sopenharmony_ci    return schedule;
78094332d3Sopenharmony_ci}
79094332d3Sopenharmony_ci
80094332d3Sopenharmony_civoid DestroyCoAuthSchedule(CoAuthSchedule *coAuthSchedule)
81094332d3Sopenharmony_ci{
82094332d3Sopenharmony_ci    if (coAuthSchedule == NULL) {
83094332d3Sopenharmony_ci        return;
84094332d3Sopenharmony_ci    }
85094332d3Sopenharmony_ci    DestroyScheduleNode(coAuthSchedule);
86094332d3Sopenharmony_ci}
87094332d3Sopenharmony_ci
88094332d3Sopenharmony_ciResultCode InitCoAuth(void)
89094332d3Sopenharmony_ci{
90094332d3Sopenharmony_ci    if (!IsCoAuthInit()) {
91094332d3Sopenharmony_ci        g_scheduleList = CreateLinkedList(DestroyScheduleNode);
92094332d3Sopenharmony_ci    }
93094332d3Sopenharmony_ci    if (g_scheduleList == NULL) {
94094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
95094332d3Sopenharmony_ci    }
96094332d3Sopenharmony_ci    return RESULT_SUCCESS;
97094332d3Sopenharmony_ci}
98094332d3Sopenharmony_ci
99094332d3Sopenharmony_civoid DestoryCoAuth(void)
100094332d3Sopenharmony_ci{
101094332d3Sopenharmony_ci    DestroyLinkedList(g_scheduleList);
102094332d3Sopenharmony_ci    g_scheduleList = NULL;
103094332d3Sopenharmony_ci}
104094332d3Sopenharmony_ci
105094332d3Sopenharmony_ciResultCode AddCoAuthSchedule(const CoAuthSchedule *coAuthSchedule)
106094332d3Sopenharmony_ci{
107094332d3Sopenharmony_ci    if (!IsCoAuthInit()) {
108094332d3Sopenharmony_ci        LOG_ERROR("pool not init");
109094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
110094332d3Sopenharmony_ci    }
111094332d3Sopenharmony_ci    if (coAuthSchedule == NULL) {
112094332d3Sopenharmony_ci        LOG_ERROR("get null schedule");
113094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
114094332d3Sopenharmony_ci    }
115094332d3Sopenharmony_ci    CoAuthSchedule *schedule = CopyCoAuthSchedule(coAuthSchedule);
116094332d3Sopenharmony_ci    if (schedule == NULL) {
117094332d3Sopenharmony_ci        LOG_ERROR("no memory");
118094332d3Sopenharmony_ci        return RESULT_NO_MEMORY;
119094332d3Sopenharmony_ci    }
120094332d3Sopenharmony_ci    if (g_scheduleList->getSize(g_scheduleList) >= MAX_SCHEDULE_NUM) {
121094332d3Sopenharmony_ci        LOG_ERROR("too many schedules already");
122094332d3Sopenharmony_ci        DestroyCoAuthSchedule(schedule);
123094332d3Sopenharmony_ci        return RESULT_GENERAL_ERROR;
124094332d3Sopenharmony_ci    }
125094332d3Sopenharmony_ci    ResultCode result = g_scheduleList->insert(g_scheduleList, schedule);
126094332d3Sopenharmony_ci    if (result != RESULT_SUCCESS) {
127094332d3Sopenharmony_ci        LOG_ERROR("insert failed");
128094332d3Sopenharmony_ci        DestroyCoAuthSchedule(schedule);
129094332d3Sopenharmony_ci    }
130094332d3Sopenharmony_ci    LOG_INFO("success");
131094332d3Sopenharmony_ci    return result;
132094332d3Sopenharmony_ci}
133094332d3Sopenharmony_ci
134094332d3Sopenharmony_ciIAM_STATIC bool IsScheduleMatch(const void *data, const void *condition)
135094332d3Sopenharmony_ci{
136094332d3Sopenharmony_ci    if ((condition == NULL) || (data == NULL)) {
137094332d3Sopenharmony_ci        LOG_ERROR("get null data");
138094332d3Sopenharmony_ci        return false;
139094332d3Sopenharmony_ci    }
140094332d3Sopenharmony_ci    uint64_t scheduleId = *(const uint64_t *)condition;
141094332d3Sopenharmony_ci    const CoAuthSchedule *coAuthSchedule = (const CoAuthSchedule *)data;
142094332d3Sopenharmony_ci    return (coAuthSchedule->scheduleId == scheduleId);
143094332d3Sopenharmony_ci}
144094332d3Sopenharmony_ci
145094332d3Sopenharmony_ciResultCode RemoveCoAuthSchedule(uint64_t scheduleId)
146094332d3Sopenharmony_ci{
147094332d3Sopenharmony_ci    if (!IsCoAuthInit()) {
148094332d3Sopenharmony_ci        LOG_ERROR("pool not init");
149094332d3Sopenharmony_ci        return RESULT_NEED_INIT;
150094332d3Sopenharmony_ci    }
151094332d3Sopenharmony_ci    return g_scheduleList->remove(g_scheduleList, (void *)&scheduleId, IsScheduleMatch, true);
152094332d3Sopenharmony_ci}
153094332d3Sopenharmony_ci
154094332d3Sopenharmony_ciconst CoAuthSchedule *GetCoAuthSchedule(uint64_t scheduleId)
155094332d3Sopenharmony_ci{
156094332d3Sopenharmony_ci    if (!IsCoAuthInit()) {
157094332d3Sopenharmony_ci        LOG_ERROR("pool not init");
158094332d3Sopenharmony_ci        return NULL;
159094332d3Sopenharmony_ci    }
160094332d3Sopenharmony_ci    LinkedListIterator *iterator = g_scheduleList->createIterator(g_scheduleList);
161094332d3Sopenharmony_ci    if (iterator == NULL) {
162094332d3Sopenharmony_ci        LOG_ERROR("create iterator failed");
163094332d3Sopenharmony_ci        return NULL;
164094332d3Sopenharmony_ci    }
165094332d3Sopenharmony_ci    CoAuthSchedule *schedule = NULL;
166094332d3Sopenharmony_ci    while (iterator->hasNext(iterator)) {
167094332d3Sopenharmony_ci        schedule = (CoAuthSchedule *)iterator->next(iterator);
168094332d3Sopenharmony_ci        if (schedule == NULL) {
169094332d3Sopenharmony_ci            LOG_ERROR("list node is null, please check");
170094332d3Sopenharmony_ci            continue;
171094332d3Sopenharmony_ci        }
172094332d3Sopenharmony_ci        if (schedule->scheduleId != scheduleId) {
173094332d3Sopenharmony_ci            continue;
174094332d3Sopenharmony_ci        }
175094332d3Sopenharmony_ci        g_scheduleList->destroyIterator(iterator);
176094332d3Sopenharmony_ci        return schedule;
177094332d3Sopenharmony_ci    }
178094332d3Sopenharmony_ci    g_scheduleList->destroyIterator(iterator);
179094332d3Sopenharmony_ci    LOG_ERROR("can't find this schedule");
180094332d3Sopenharmony_ci    return NULL;
181094332d3Sopenharmony_ci}
182094332d3Sopenharmony_ci
183094332d3Sopenharmony_ciIAM_STATIC bool IsScheduleIdDuplicate(uint64_t scheduleId)
184094332d3Sopenharmony_ci{
185094332d3Sopenharmony_ci    LinkedListNode *temp = g_scheduleList->head;
186094332d3Sopenharmony_ci    CoAuthSchedule *schedule = NULL;
187094332d3Sopenharmony_ci    while (temp != NULL) {
188094332d3Sopenharmony_ci        schedule = (CoAuthSchedule *)temp->data;
189094332d3Sopenharmony_ci        if (schedule != NULL && schedule->scheduleId == scheduleId) {
190094332d3Sopenharmony_ci            return true;
191094332d3Sopenharmony_ci        }
192094332d3Sopenharmony_ci        temp = temp->next;
193094332d3Sopenharmony_ci    }
194094332d3Sopenharmony_ci
195094332d3Sopenharmony_ci    return false;
196094332d3Sopenharmony_ci}
197094332d3Sopenharmony_ci
198094332d3Sopenharmony_ciIAM_STATIC ResultCode GenerateValidScheduleId(uint64_t *scheduleId)
199094332d3Sopenharmony_ci{
200094332d3Sopenharmony_ci    if (g_scheduleList == NULL) {
201094332d3Sopenharmony_ci        LOG_ERROR("g_poolList is null");
202094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
203094332d3Sopenharmony_ci    }
204094332d3Sopenharmony_ci
205094332d3Sopenharmony_ci    for (uint32_t i = 0; i < MAX_DUPLICATE_CHECK; ++i) {
206094332d3Sopenharmony_ci        uint64_t tempRandom;
207094332d3Sopenharmony_ci        if (SecureRandom((uint8_t *)&tempRandom, sizeof(uint64_t)) != RESULT_SUCCESS) {
208094332d3Sopenharmony_ci            LOG_ERROR("get random failed");
209094332d3Sopenharmony_ci            return RESULT_GENERAL_ERROR;
210094332d3Sopenharmony_ci        }
211094332d3Sopenharmony_ci        if (!IsScheduleIdDuplicate(tempRandom)) {
212094332d3Sopenharmony_ci            *scheduleId = tempRandom;
213094332d3Sopenharmony_ci            return RESULT_SUCCESS;
214094332d3Sopenharmony_ci        }
215094332d3Sopenharmony_ci    }
216094332d3Sopenharmony_ci
217094332d3Sopenharmony_ci    LOG_ERROR("a rare failure");
218094332d3Sopenharmony_ci    return RESULT_GENERAL_ERROR;
219094332d3Sopenharmony_ci}
220094332d3Sopenharmony_ci
221094332d3Sopenharmony_ciIAM_STATIC ResultCode MountExecutorOnce(const LinkedList *executors, CoAuthSchedule *coAuthSchedule,
222094332d3Sopenharmony_ci    uint32_t sensorHint, uint32_t executorRole, Uint8Array deviceUdid)
223094332d3Sopenharmony_ci{
224094332d3Sopenharmony_ci    LinkedListNode *tempNode = executors->head;
225094332d3Sopenharmony_ci    while (tempNode != NULL) {
226094332d3Sopenharmony_ci        if (tempNode->data == NULL) {
227094332d3Sopenharmony_ci            LOG_ERROR("data is null");
228094332d3Sopenharmony_ci            return RESULT_UNKNOWN;
229094332d3Sopenharmony_ci        }
230094332d3Sopenharmony_ci        ExecutorInfoHal *executor = (ExecutorInfoHal *)tempNode->data;
231094332d3Sopenharmony_ci        if (executor->executorRole != executorRole) {
232094332d3Sopenharmony_ci            tempNode = tempNode->next;
233094332d3Sopenharmony_ci            continue;
234094332d3Sopenharmony_ci        }
235094332d3Sopenharmony_ci        if (sensorHint != INVALID_SENSOR_HINT && sensorHint != executor->executorSensorHint) {
236094332d3Sopenharmony_ci            tempNode = tempNode->next;
237094332d3Sopenharmony_ci            continue;
238094332d3Sopenharmony_ci        }
239094332d3Sopenharmony_ci
240094332d3Sopenharmony_ci        if (memcmp(deviceUdid.data, executor->deviceUdid, UDID_LEN) != 0) {
241094332d3Sopenharmony_ci            tempNode = tempNode->next;
242094332d3Sopenharmony_ci            continue;
243094332d3Sopenharmony_ci        }
244094332d3Sopenharmony_ci        coAuthSchedule->executors[coAuthSchedule->executorSize] = *executor;
245094332d3Sopenharmony_ci        ++(coAuthSchedule->executorSize);
246094332d3Sopenharmony_ci        return RESULT_SUCCESS;
247094332d3Sopenharmony_ci    }
248094332d3Sopenharmony_ci    LOG_ERROR("mount executor failed");
249094332d3Sopenharmony_ci    return RESULT_NOT_FOUND;
250094332d3Sopenharmony_ci}
251094332d3Sopenharmony_ci
252094332d3Sopenharmony_ciIAM_STATIC ResultCode MountExecutor(const ScheduleParam *param, CoAuthSchedule *coAuthSchedule)
253094332d3Sopenharmony_ci{
254094332d3Sopenharmony_ci    ExecutorCondition condition = {};
255094332d3Sopenharmony_ci    SetExecutorConditionAuthType(&condition, param->authType);
256094332d3Sopenharmony_ci    if (param->collectorSensorHint != INVALID_SENSOR_HINT || param->verifierSensorHint != INVALID_SENSOR_HINT) {
257094332d3Sopenharmony_ci        SetExecutorConditionExecutorMatcher(&condition, param->executorMatcher);
258094332d3Sopenharmony_ci    }
259094332d3Sopenharmony_ci    LinkedList *executors = QueryExecutor(&condition);
260094332d3Sopenharmony_ci    if (executors == NULL) {
261094332d3Sopenharmony_ci        LOG_ERROR("query executor failed");
262094332d3Sopenharmony_ci        return RESULT_UNKNOWN;
263094332d3Sopenharmony_ci    }
264094332d3Sopenharmony_ci
265094332d3Sopenharmony_ci    Uint8Array localUdidArray = { .data = (uint8_t *)(param->localUdid), .len = UDID_LEN };
266094332d3Sopenharmony_ci    Uint8Array collectorUdidArray = { .data = (uint8_t *)(param->collectorUdid), .len = UDID_LEN };
267094332d3Sopenharmony_ci    ResultCode ret;
268094332d3Sopenharmony_ci    LOG_INFO("collectorSensorHint: %{public}u, verifierSensorHint: %{public}u", param->collectorSensorHint,
269094332d3Sopenharmony_ci        param->verifierSensorHint);
270094332d3Sopenharmony_ci    if ((param->collectorSensorHint == INVALID_SENSOR_HINT || param->verifierSensorHint == INVALID_SENSOR_HINT ||
271094332d3Sopenharmony_ci        param->collectorSensorHint == param->verifierSensorHint) &&
272094332d3Sopenharmony_ci        memcmp(param->localUdid, param->collectorUdid, UDID_LEN) == 0) {
273094332d3Sopenharmony_ci        uint32_t allInOneSensorHint = param->verifierSensorHint | param->collectorSensorHint;
274094332d3Sopenharmony_ci        LOG_INFO("mount all-in-one executor");
275094332d3Sopenharmony_ci        ret = MountExecutorOnce(executors, coAuthSchedule, allInOneSensorHint, ALL_IN_ONE, localUdidArray);
276094332d3Sopenharmony_ci        if (ret != RESULT_SUCCESS) {
277094332d3Sopenharmony_ci            LOG_INFO("all-in-one executor is not found");
278094332d3Sopenharmony_ci        }
279094332d3Sopenharmony_ci        goto EXIT;
280094332d3Sopenharmony_ci    }
281094332d3Sopenharmony_ci
282094332d3Sopenharmony_ci    LOG_INFO("mount verifier and collector");
283094332d3Sopenharmony_ci    if (param->scheduleMode == SCHEDULE_MODE_IDENTIFY) {
284094332d3Sopenharmony_ci        LOG_ERROR("identification only supports all in one");
285094332d3Sopenharmony_ci        ret = RESULT_GENERAL_ERROR;
286094332d3Sopenharmony_ci        goto EXIT;
287094332d3Sopenharmony_ci    }
288094332d3Sopenharmony_ci    ret = MountExecutorOnce(executors, coAuthSchedule, param->verifierSensorHint, VERIFIER, localUdidArray);
289094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
290094332d3Sopenharmony_ci        LOG_ERROR("verifier is not found");
291094332d3Sopenharmony_ci        goto EXIT;
292094332d3Sopenharmony_ci    }
293094332d3Sopenharmony_ci
294094332d3Sopenharmony_ci    ret = MountExecutorOnce(executors, coAuthSchedule, param->collectorSensorHint, COLLECTOR, collectorUdidArray);
295094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
296094332d3Sopenharmony_ci        LOG_ERROR("collector is not found");
297094332d3Sopenharmony_ci    }
298094332d3Sopenharmony_ci
299094332d3Sopenharmony_ciEXIT:
300094332d3Sopenharmony_ci    DestroyLinkedList(executors);
301094332d3Sopenharmony_ci    return ret;
302094332d3Sopenharmony_ci}
303094332d3Sopenharmony_ci
304094332d3Sopenharmony_ciuint32_t GetScheduleVerifierSensorHint(const CoAuthSchedule *coAuthSchedule)
305094332d3Sopenharmony_ci{
306094332d3Sopenharmony_ci    if (coAuthSchedule == NULL) {
307094332d3Sopenharmony_ci        LOG_ERROR("coAuthSchedule is null");
308094332d3Sopenharmony_ci        return INVALID_SENSOR_HINT;
309094332d3Sopenharmony_ci    }
310094332d3Sopenharmony_ci    for (uint32_t i = 0; i < coAuthSchedule->executorSize; ++i) {
311094332d3Sopenharmony_ci        const ExecutorInfoHal *executor = coAuthSchedule->executors + i;
312094332d3Sopenharmony_ci        if (executor->executorRole == VERIFIER || executor->executorRole == ALL_IN_ONE) {
313094332d3Sopenharmony_ci            return executor->executorSensorHint;
314094332d3Sopenharmony_ci        }
315094332d3Sopenharmony_ci    }
316094332d3Sopenharmony_ci    LOG_ERROR("not found");
317094332d3Sopenharmony_ci    return INVALID_SENSOR_HINT;
318094332d3Sopenharmony_ci}
319094332d3Sopenharmony_ci
320094332d3Sopenharmony_ciCoAuthSchedule *GenerateSchedule(const ScheduleParam *param)
321094332d3Sopenharmony_ci{
322094332d3Sopenharmony_ci    if (param == NULL) {
323094332d3Sopenharmony_ci        LOG_ERROR("param is invalid");
324094332d3Sopenharmony_ci        return NULL;
325094332d3Sopenharmony_ci    }
326094332d3Sopenharmony_ci    CoAuthSchedule *coAuthSchedule = Malloc(sizeof(CoAuthSchedule));
327094332d3Sopenharmony_ci    if (coAuthSchedule == NULL) {
328094332d3Sopenharmony_ci        LOG_ERROR("coAuthSchedule is null");
329094332d3Sopenharmony_ci        return NULL;
330094332d3Sopenharmony_ci    }
331094332d3Sopenharmony_ci    if (memset_s(coAuthSchedule, sizeof(CoAuthSchedule), 0, sizeof(CoAuthSchedule)) != EOK) {
332094332d3Sopenharmony_ci        LOG_ERROR("reset coAuthSchedule failed");
333094332d3Sopenharmony_ci        Free(coAuthSchedule);
334094332d3Sopenharmony_ci        return NULL;
335094332d3Sopenharmony_ci    }
336094332d3Sopenharmony_ci    ResultCode ret = GenerateValidScheduleId(&coAuthSchedule->scheduleId);
337094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
338094332d3Sopenharmony_ci        LOG_ERROR("get scheduleId failed");
339094332d3Sopenharmony_ci        goto FAIL;
340094332d3Sopenharmony_ci    }
341094332d3Sopenharmony_ci    coAuthSchedule->associateId = param->associateId;
342094332d3Sopenharmony_ci    coAuthSchedule->scheduleMode = param->scheduleMode;
343094332d3Sopenharmony_ci    coAuthSchedule->authType = param->authType;
344094332d3Sopenharmony_ci    coAuthSchedule->userType = param->userType;
345094332d3Sopenharmony_ci    if (param->templateIds != NULL) {
346094332d3Sopenharmony_ci        ret = CopyTemplateArrays(param->templateIds, &(coAuthSchedule->templateIds));
347094332d3Sopenharmony_ci        if (ret != RESULT_SUCCESS) {
348094332d3Sopenharmony_ci            LOG_ERROR("copy template failed");
349094332d3Sopenharmony_ci            goto FAIL;
350094332d3Sopenharmony_ci        }
351094332d3Sopenharmony_ci    }
352094332d3Sopenharmony_ci
353094332d3Sopenharmony_ci    ret = MountExecutor(param, coAuthSchedule);
354094332d3Sopenharmony_ci    if (ret != RESULT_SUCCESS) {
355094332d3Sopenharmony_ci        LOG_ERROR("mount failed");
356094332d3Sopenharmony_ci        goto FAIL;
357094332d3Sopenharmony_ci    }
358094332d3Sopenharmony_ci    return coAuthSchedule;
359094332d3Sopenharmony_ciFAIL:
360094332d3Sopenharmony_ci    DestroyCoAuthSchedule(coAuthSchedule);
361094332d3Sopenharmony_ci    return NULL;
362094332d3Sopenharmony_ci}
363094332d3Sopenharmony_ci
364094332d3Sopenharmony_cibool IsTemplateArraysValid(const Uint64Array *templateIds)
365094332d3Sopenharmony_ci{
366094332d3Sopenharmony_ci    if (templateIds == NULL) {
367094332d3Sopenharmony_ci        LOG_ERROR("templateIds is null");
368094332d3Sopenharmony_ci        return false;
369094332d3Sopenharmony_ci    }
370094332d3Sopenharmony_ci    if (templateIds->len > MAX_TEMPLATE_OF_SCHEDULE || (templateIds->len != 0 && templateIds->data == NULL)) {
371094332d3Sopenharmony_ci        LOG_ERROR("templateIds's content is invalid");
372094332d3Sopenharmony_ci        return false;
373094332d3Sopenharmony_ci    }
374094332d3Sopenharmony_ci    return true;
375094332d3Sopenharmony_ci}
376094332d3Sopenharmony_ci
377094332d3Sopenharmony_ciResultCode CopyTemplateArrays(const Uint64Array *in, Uint64Array *out)
378094332d3Sopenharmony_ci{
379094332d3Sopenharmony_ci    if (!IsTemplateArraysValid(in) || out == NULL || out->data != NULL) {
380094332d3Sopenharmony_ci        LOG_ERROR("param is invalid");
381094332d3Sopenharmony_ci        return RESULT_BAD_PARAM;
382094332d3Sopenharmony_ci    }
383094332d3Sopenharmony_ci    if (in->len == 0) {
384094332d3Sopenharmony_ci        out->len = 0;
385094332d3Sopenharmony_ci        return RESULT_SUCCESS;
386094332d3Sopenharmony_ci    }
387094332d3Sopenharmony_ci    out->len = in->len;
388094332d3Sopenharmony_ci    out->data = (uint64_t *)Malloc(sizeof(uint64_t) * out->len);
389094332d3Sopenharmony_ci    if (out->data == NULL) {
390094332d3Sopenharmony_ci        LOG_ERROR("out data is null");
391094332d3Sopenharmony_ci        out->len = 0;
392094332d3Sopenharmony_ci        return RESULT_NO_MEMORY;
393094332d3Sopenharmony_ci    }
394094332d3Sopenharmony_ci    if (memcpy_s(out->data, (sizeof(uint64_t) * out->len), in->data, (sizeof(uint64_t) * in->len)) != EOK) {
395094332d3Sopenharmony_ci        LOG_ERROR("copy failed");
396094332d3Sopenharmony_ci        Free(out->data);
397094332d3Sopenharmony_ci        out->data = NULL;
398094332d3Sopenharmony_ci        out->len = 0;
399094332d3Sopenharmony_ci        return RESULT_BAD_COPY;
400094332d3Sopenharmony_ci    }
401094332d3Sopenharmony_ci    return RESULT_SUCCESS;
402094332d3Sopenharmony_ci}