1 /*
2  * Copyright (c) 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 "pin_db_ops.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_log.h"
21 #include "adaptor_memory.h"
22 #include "file_operator.h"
23 
24 #include "pin_db_ops.h"
25 
26 #define DB_VERSION_CURRENT DB_VERSION_1
27 
28 typedef struct PinDbOps {
29     void *(*getDb)(uint8_t *data, uint32_t dataLen);
30     void *(*updateDb)(void *preDb);
31     void (*freeDb)(void **pinDb);
32 } PinDbOps;
33 
34 PinDbOps g_pinDbOps[] = {
35     {
36         .getDb = GetPinDbV0,
37         .updateDb = NULL,
38         .freeDb = FreePinDbV0,
39     },
40     {
41         .getDb = GetPinDbV1,
42         .updateDb = UpdatePinDbFrom0To1,
43         .freeDb = FreePinDbV1,
44     },
45 };
46 
GetVersion(uint8_t * data,uint32_t dataLen,uint32_t * version)47 static ResultCode GetVersion(uint8_t *data, uint32_t dataLen, uint32_t *version)
48 {
49     if (data == NULL || dataLen == 0) {
50         *version = DB_VERSION_CURRENT;
51         LOG_INFO("db file not exist current version:%{public}u.", DB_VERSION_CURRENT);
52         return RESULT_SUCCESS;
53     }
54 
55     uint8_t *temp = data;
56     uint32_t tempLen = dataLen;
57     if (GetDataFromBuf(&temp, &tempLen, (uint8_t *)(version), sizeof(uint32_t)) != RESULT_SUCCESS) {
58         LOG_ERROR("read version fail.");
59         return RESULT_GENERAL_ERROR;
60     }
61 
62     LOG_INFO("read version:%{public}u, current version:%{public}u.", *version, DB_VERSION_CURRENT);
63     return RESULT_SUCCESS;
64 }
65 
LoadAndUpdatePinDb(uint8_t * data,uint32_t dataLen)66 static void *LoadAndUpdatePinDb(uint8_t *data, uint32_t dataLen)
67 {
68     uint32_t version = DB_VERSION_CURRENT;
69     if (GetVersion(data, dataLen, &version) != RESULT_SUCCESS) {
70         LOG_ERROR("get version fail.");
71         return NULL;
72     }
73     if (version > DB_VERSION_CURRENT) {
74         LOG_ERROR("read version invalid.");
75         return NULL;
76     }
77     void *pinDb = g_pinDbOps[version].getDb(data, dataLen);
78     if (pinDb == NULL) {
79         LOG_ERROR("get db fail.");
80         return NULL;
81     }
82     if (version == DB_VERSION_CURRENT) {
83         return pinDb;
84     }
85     while (version < DB_VERSION_CURRENT) {
86         void *pinDbPre = pinDb;
87         pinDb = g_pinDbOps[version + 1].updateDb(pinDbPre);
88         g_pinDbOps[version].freeDb(&pinDbPre);
89         if (pinDb == NULL) {
90             LOG_ERROR("update db fail.");
91             return NULL;
92         }
93         version++;
94     }
95     if (WritePinDb(pinDb) != RESULT_SUCCESS) {
96         LOG_ERROR("WritePinDb fail.");
97         g_pinDbOps[version].freeDb(&pinDb);
98         return NULL;
99     }
100 
101     return pinDb;
102 }
103 
ReadPinDbData(uint8_t ** data,uint32_t * dataLen)104 static ResultCode ReadPinDbData(uint8_t **data, uint32_t *dataLen)
105 {
106     FileOperator *fileOp = GetFileOperator(DEFAULT_FILE_OPERATOR);
107     if (!IsFileOperatorValid(fileOp)) {
108         LOG_ERROR("fileOp invalid.");
109         return RESULT_GENERAL_ERROR;
110     }
111 
112     if (!fileOp->isFileExist(PIN_INDEX_NAME)) {
113         LOG_INFO("pin file not found.");
114         *data = NULL;
115         *dataLen = 0;
116         return RESULT_SUCCESS;
117     }
118 
119     ResultCode ret = (ResultCode)(fileOp->getFileLen(PIN_INDEX_NAME, dataLen));
120     if (ret != RESULT_SUCCESS) {
121         LOG_ERROR("getFileLen failed");
122         return RESULT_BAD_READ;
123     }
124 
125     *data = Malloc(*dataLen);
126     if ((*data) == NULL) {
127         LOG_ERROR("malloc data failed");
128         return RESULT_GENERAL_ERROR;
129     }
130     ret = (ResultCode)fileOp->readFile(PIN_INDEX_NAME, *data, *dataLen);
131     if (ret != RESULT_SUCCESS) {
132         LOG_ERROR("readFile failed.");
133         (void)memset_s(*data, *dataLen, 0, *dataLen);
134         Free(*data);
135         *data = NULL;
136         *dataLen = 0;
137         return RESULT_BAD_READ;
138     }
139     return RESULT_SUCCESS;
140 }
141 
ReadPinDb(void)142 PinDbV1 *ReadPinDb(void)
143 {
144     uint8_t *data = NULL;
145     uint32_t dataLen = 0;
146     ResultCode ret = ReadPinDbData(&data, &dataLen);
147     if (ret != RESULT_SUCCESS) {
148         LOG_ERROR("ReadPinDbData fail.");
149         return NULL;
150     }
151     PinDbV1 *pinDb = LoadAndUpdatePinDb(data, dataLen);
152     if (data != NULL) {
153         (void)memset_s(data, dataLen, 0, dataLen);
154         Free(data);
155     }
156     if (pinDb == NULL) {
157         LOG_ERROR("LoadAndUpdatePinDb fail.");
158     }
159 
160     return pinDb;
161 }
162 
WritePinDb(PinDbV1 * pinDbV1)163 ResultCode WritePinDb(PinDbV1 *pinDbV1)
164 {
165     return WritePinDbV1((void *)pinDbV1);
166 }
167 
FreePinDb(PinDbV1 ** pinDbV1)168 void FreePinDb(PinDbV1 **pinDbV1)
169 {
170     FreePinDbV1((void **)(pinDbV1));
171 }
172