1 /*
2  * Copyright (c) 2024 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 "executor_func_common.h"
17 
18 #include <inttypes.h>
19 
20 #include "securec.h"
21 
22 #include "adaptor_algorithm.h"
23 #include "adaptor_log.h"
24 #include "adaptor_memory.h"
25 #include "adaptor_time.h"
26 #include "attribute.h"
27 
SetBufferToAttribute(Attribute * attribute,AttributeKey key,Buffer * buf)28 int32_t SetBufferToAttribute(Attribute *attribute, AttributeKey key, Buffer *buf)
29 {
30     if ((attribute == NULL) || !IsBufferValid(buf)) {
31         LOG_ERROR("SetBufferToAttribute bad param!");
32         return RESULT_BAD_PARAM;
33     }
34     Uint8Array uint8Array = {
35         .data = buf->buf,
36         .len = buf->contentSize,
37     };
38     return SetAttributeUint8Array(attribute, key, uint8Array);
39 }
40 
GetBufferFromAttributeBase(const Attribute * attribute,AttributeKey key,bool checkSize,uint32_t size)41 static Buffer *GetBufferFromAttributeBase(const Attribute *attribute, AttributeKey key, bool checkSize, uint32_t size)
42 {
43     if (attribute == NULL) {
44         LOG_ERROR("GetBufferFromAttributeBase bad param!");
45         return NULL;
46     }
47     uint32_t len = 0;
48     int32_t result = GetAttributeLength(attribute, key, &len);
49     if ((result != RESULT_SUCCESS) || (checkSize && (len != size))) {
50         LOG_ERROR("get attribute:%{public}d length:%{public}u fail!", key, len);
51         return NULL;
52     }
53 
54     Buffer *buffer = CreateBufferBySize(len);
55     IF_TRUE_LOGE_AND_RETURN_VAL(buffer == NULL, NULL);
56 
57     Uint8Array uint8Array = {
58         .data = buffer->buf,
59         .len = buffer->maxSize,
60     };
61     result = GetAttributeUint8Array(attribute, key, &uint8Array);
62     if (result != RESULT_SUCCESS) {
63         LOG_ERROR("get attrbute %{public}d fail!", key);
64         DestroyBuffer(buffer);
65         return NULL;
66     }
67     buffer->contentSize = uint8Array.len;
68     return buffer;
69 }
70 
GetBufferFromAttribute(const Attribute * attribute,AttributeKey key,uint32_t size)71 Buffer *GetBufferFromAttribute(const Attribute *attribute, AttributeKey key, uint32_t size)
72 {
73     return GetBufferFromAttributeBase(attribute, key, true, size);
74 }
75 
GetAttributeDataBase(uint64_t scheduleId,RemotePinMsgId msgId)76 Attribute *GetAttributeDataBase(uint64_t scheduleId, RemotePinMsgId msgId)
77 {
78     Attribute *attribute = CreateEmptyAttribute();
79     IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, NULL);
80 
81     int32_t result = SetAttributeUint64(attribute, ATTR_SCHEDULE_ID, scheduleId);
82     if (result != RESULT_SUCCESS) {
83         LOG_ERROR("set schedule id fail!");
84         FreeAttribute(&attribute);
85         return NULL;
86     }
87 
88     if (msgId != REMOTE_PIN_MSG_NONE) {
89         result = SetAttributeUint64(attribute, ATTR_TIME_STAMP, GetRtcTime());
90         if (result != RESULT_SUCCESS) {
91             LOG_ERROR("set time stamp fail!");
92             FreeAttribute(&attribute);
93             return NULL;
94         }
95 
96         result = SetAttributeUint32(attribute, PIN_ATTR_MSG_ID, msgId);
97         if (result != RESULT_SUCCESS) {
98             LOG_ERROR("set msg id fail!");
99             FreeAttribute(&attribute);
100             return NULL;
101         }
102     }
103 
104     return attribute;
105 }
106 
GetRootMsg(const Attribute * data,const KeyPair * keyPair,Uint8Array * rootMsg)107 static int32_t GetRootMsg(const Attribute *data, const KeyPair *keyPair, Uint8Array *rootMsg)
108 {
109     Uint8Array dataMsg = {
110         .data = rootMsg->data,
111         .len = rootMsg->len
112     };
113     int32_t result = GetAttributeSerializedMsg(data, &dataMsg);
114     if (result != RESULT_SUCCESS) {
115         LOG_ERROR("GetAttributeSerializedMsg fail!");
116         return result;
117     }
118 
119     Buffer dataBuf = GetTmpBuffer(dataMsg.data, dataMsg.len, dataMsg.len);
120     Buffer *sign = NULL;
121     Attribute *attribute = NULL;
122     result = Ed25519Sign(keyPair, &dataBuf, &sign);
123     if (result != RESULT_SUCCESS) {
124         LOG_ERROR("Ed25519Sign fail!");
125         goto EXIT;
126     }
127     attribute = CreateEmptyAttribute();
128     if (attribute == NULL) {
129         LOG_ERROR("get root fail!");
130         result = RESULT_GENERAL_ERROR;
131         goto EXIT;
132     }
133 
134     result = SetBufferToAttribute(attribute, ATTR_DATA, &dataBuf);
135     if (result != RESULT_SUCCESS) {
136         LOG_ERROR("set data fail!");
137         goto EXIT;
138     }
139     result = SetBufferToAttribute(attribute, ATTR_SIGNATURE, sign);
140     if (result != RESULT_SUCCESS) {
141         LOG_ERROR("set sign fail!");
142         goto EXIT;
143     }
144 
145     result = GetAttributeSerializedMsg(attribute, rootMsg);
146     if (result != RESULT_SUCCESS) {
147         LOG_ERROR("get serialized root fail!");
148         goto EXIT;
149     }
150 
151 EXIT:
152     DestroyBuffer(sign);
153     FreeAttribute(&attribute);
154     return result;
155 }
156 
FormatTlvMsg(const Attribute * data,const KeyPair * keyPair,uint8_t * msg,uint32_t * msgSize)157 int32_t FormatTlvMsg(const Attribute *data, const KeyPair *keyPair, uint8_t *msg, uint32_t *msgSize)
158 {
159     if ((data == NULL) || !IsEd25519KeyPairValid(keyPair) || (msg == NULL) || (msgSize == NULL)) {
160         LOG_ERROR("FormatTlvMsg check param fail!");
161         return RESULT_BAD_PARAM;
162     }
163     Uint8Array uint8Array = {
164         .data = msg,
165         .len = *msgSize,
166     };
167     int32_t result = GetRootMsg(data, keyPair, &uint8Array);
168     if (result != RESULT_SUCCESS) {
169         LOG_ERROR("GetRootMsg fail!");
170         return result;
171     }
172     Attribute *attribute = CreateEmptyAttribute();
173     if (attribute == NULL) {
174         LOG_ERROR("create root attribute fail!");
175         result = RESULT_GENERAL_ERROR;
176         goto EXIT;
177     }
178     result = SetAttributeUint8Array(attribute, ATTR_ROOT, uint8Array);
179     if (result != RESULT_SUCCESS) {
180         LOG_ERROR("set root fail!");
181         goto EXIT;
182     }
183 
184     uint8Array.data = msg;
185     uint8Array.len = *msgSize;
186     result = GetAttributeSerializedMsg(attribute, &uint8Array);
187     if (result != RESULT_SUCCESS) {
188         LOG_ERROR("get serialized tlv fail!");
189         goto EXIT;
190     }
191     *msgSize = uint8Array.len;
192 
193 EXIT:
194     FreeAttribute(&attribute);
195     return result;
196 }
197 
GetRootAttributeFromTlv(const uint8_t * msg,uint32_t msgSize)198 static Attribute *GetRootAttributeFromTlv(const uint8_t *msg, uint32_t msgSize)
199 {
200     Uint8Array uint8Array = {
201         .data = (uint8_t *)msg,
202         .len = msgSize,
203     };
204     Attribute *attributeTlv = CreateAttributeFromSerializedMsg(uint8Array);
205     if (attributeTlv == NULL) {
206         LOG_ERROR("create root tlv fail!");
207         return NULL;
208     }
209     Buffer *root = GetBufferFromAttributeBase(attributeTlv, ATTR_ROOT, false, 0);
210     FreeAttribute(&attributeTlv);
211     if (root == NULL) {
212         LOG_ERROR("get root buffer fail!");
213         return NULL;
214     }
215 
216     uint8Array.data = root->buf;
217     uint8Array.len = root->contentSize;
218     Attribute *attributeRoot = CreateAttributeFromSerializedMsg(uint8Array);
219     DestroyBuffer(root);
220     return attributeRoot;
221 }
222 
CheckScheduleIdOfAttribute(uint64_t scheduleId,const Attribute * data)223 static bool CheckScheduleIdOfAttribute(uint64_t scheduleId, const Attribute *data)
224 {
225     uint64_t dataScheduleId = 0;
226     int32_t result = GetAttributeUint64(data, ATTR_SCHEDULE_ID, &dataScheduleId);
227     if (result != RESULT_SUCCESS) {
228         LOG_ERROR("get schedule id fail");
229         return false;
230     }
231     if (dataScheduleId != scheduleId) {
232         LOG_ERROR("data schedule:%{public}x not match current schedule:%{public}x",
233             (uint16_t)dataScheduleId, (uint16_t)scheduleId);
234         return false;
235     }
236     return true;
237 }
238 
VerifyAndGetDataAttribute(uint64_t scheduleId,Attribute ** data,const Buffer * pubKey,const uint8_t * msg,uint32_t msgSize)239 int32_t VerifyAndGetDataAttribute(
240     uint64_t scheduleId, Attribute **data, const Buffer *pubKey, const uint8_t *msg, uint32_t msgSize)
241 {
242     if ((data == NULL) || !IsBufferValid(pubKey) || (msg == NULL)) {
243         LOG_ERROR("VerifyAndGetDataAttribute check param fail!");
244         return RESULT_BAD_PARAM;
245     }
246 
247     Attribute *attributeRoot = GetRootAttributeFromTlv(msg, msgSize);
248     if (attributeRoot == NULL) {
249         LOG_ERROR("get root fail!");
250         return RESULT_GENERAL_ERROR;
251     }
252 
253     Buffer *dataBuf = GetBufferFromAttributeBase(attributeRoot, ATTR_DATA, false, 0);
254     Buffer *signBuf = GetBufferFromAttributeBase(attributeRoot, ATTR_SIGNATURE, false, 0);
255     FreeAttribute(&attributeRoot);
256     if ((dataBuf == NULL) || (signBuf == NULL)) {
257         LOG_ERROR("get data or sign buffer fail!");
258         DestroyBuffer(dataBuf);
259         DestroyBuffer(signBuf);
260         return RESULT_GENERAL_ERROR;
261     }
262 
263     int32_t result = Ed25519Verify(pubKey, dataBuf, signBuf);
264     DestroyBuffer(signBuf);
265     if (result != RESULT_SUCCESS) {
266         LOG_ERROR("verify data signature fail!");
267         DestroyBuffer(dataBuf);
268         return RESULT_GENERAL_ERROR;
269     }
270 
271     Uint8Array uint8Array = {
272         .data = dataBuf->buf,
273         .len = dataBuf->contentSize,
274     };
275     *data = CreateAttributeFromSerializedMsg(uint8Array);
276     DestroyBuffer(dataBuf);
277     if ((*data) == NULL) {
278         LOG_ERROR("create data fail!");
279         return RESULT_GENERAL_ERROR;
280     }
281 
282     if (!CheckScheduleIdOfAttribute(scheduleId, *data)) {
283         LOG_ERROR("CheckScheduleIdOfAttribute fail!");
284         FreeAttribute(data);
285         *data = NULL;
286         return RESULT_GENERAL_ERROR;
287     }
288 
289     return RESULT_SUCCESS;
290 }
291 
CheckAttributeDataBase(const Attribute * data,uint64_t scheduleId,RemotePinMsgId msgId,uint64_t * timeStamp)292 int32_t CheckAttributeDataBase(const Attribute *data, uint64_t scheduleId, RemotePinMsgId msgId, uint64_t *timeStamp)
293 {
294     if ((data == NULL) || (timeStamp == NULL)) {
295         LOG_ERROR("CheckAttributeDataBase check param fail!");
296         return RESULT_BAD_PARAM;
297     }
298 
299     if (!CheckScheduleIdOfAttribute(scheduleId, data)) {
300         LOG_ERROR("CheckScheduleIdOfAttribute fail!");
301         return RESULT_BAD_MATCH;
302     }
303 
304     uint32_t dataMsgId = 0;
305     int32_t result = GetAttributeUint32(data, PIN_ATTR_MSG_ID, &dataMsgId);
306     if (result != RESULT_SUCCESS) {
307         LOG_ERROR("get msg id fail");
308         return result;
309     }
310     if (dataMsgId != msgId) {
311         LOG_ERROR("data msgId:%{public}u not match current msgId:%{public}u", dataMsgId, msgId);
312         return RESULT_BAD_MATCH;
313     }
314 
315     uint64_t dataTimeStamp = 0;
316     result = GetAttributeUint64(data, ATTR_TIME_STAMP, &dataTimeStamp);
317     if (result != RESULT_SUCCESS) {
318         LOG_ERROR("get time stamp fail");
319         return result;
320     }
321     if (dataTimeStamp <= (*timeStamp)) {
322         LOG_ERROR("data time:%{public}" PRIu64 " not match current time:%{public}" PRIu64,
323             dataTimeStamp, (*timeStamp));
324         return RESULT_BAD_MATCH;
325     }
326     (*timeStamp) = dataTimeStamp;
327 
328     return RESULT_SUCCESS;
329 }
330 
GetSubTypeAndFreezeTime(uint64_t * subType,uint64_t templateId,uint32_t * freezeTime,uint32_t * count)331 static ResultCode GetSubTypeAndFreezeTime(
332     uint64_t *subType, uint64_t templateId, uint32_t *freezeTime, uint32_t *count)
333 {
334     ResultCode ret = GetSubType(templateId, subType);
335     if (ret != RESULT_SUCCESS) {
336         LOG_ERROR("GetSubType fail.");
337         return ret;
338     }
339     uint64_t startFreezeTime = INIT_START_FREEZE_TIMES;
340     ret = GetAntiBruteInfo(templateId, count, &startFreezeTime);
341     if (ret != RESULT_SUCCESS) {
342         LOG_ERROR("GetAntiBruteInfo fail.");
343         return ret;
344     }
345 
346     ret = ComputeFreezeTime(templateId, freezeTime, *count, startFreezeTime);
347     if (ret != RESULT_SUCCESS) {
348         LOG_ERROR("ComputeFreezeTime fail.");
349         return ret;
350     }
351     return RESULT_SUCCESS;
352 }
353 
DoQueryPinInfo(uint64_t templateId,PinCredentialInfos * pinCredentialInfo)354 int32_t DoQueryPinInfo(uint64_t templateId, PinCredentialInfos *pinCredentialInfo)
355 {
356     if (pinCredentialInfo == NULL || templateId == INVALID_TEMPLATE_ID) {
357         LOG_ERROR("check DoQueryPin param fail!");
358         return RESULT_BAD_PARAM;
359     }
360     uint32_t authErrorCount = INIT_AUTH_ERROR_COUNT;
361     ResultCode ret = GetSubTypeAndFreezeTime(&(pinCredentialInfo->subType), templateId,
362         &(pinCredentialInfo->freezeTime), &authErrorCount);
363     if (ret != RESULT_SUCCESS) {
364         LOG_ERROR("GetSubTypeAndFreezeTime fail.");
365         return ret;
366     }
367     pinCredentialInfo->nextFailLockoutDuration = GetNextFailLockoutDuration(authErrorCount);
368     if (pinCredentialInfo->freezeTime > 0) {
369         pinCredentialInfo->remainTimes = 0;
370     } else {
371         ret = GetRemainTimes(templateId, &(pinCredentialInfo->remainTimes), authErrorCount);
372         if (ret != RESULT_SUCCESS) {
373             LOG_ERROR("GetRemainTimes fail.");
374             return ret;
375         }
376     }
377     return ret;
378 }
379 
SetResultDataInfo(Attribute * attribute,int32_t resultCode,uint64_t templateId,Buffer * rootSecret)380 bool SetResultDataInfo(Attribute *attribute, int32_t resultCode, uint64_t templateId, Buffer *rootSecret)
381 {
382     if ((attribute == NULL) || ((rootSecret != NULL) && !IsBufferValid(rootSecret))) {
383         LOG_ERROR("SetResultDataInfo check param fail");
384         return false;
385     }
386 
387     PinCredentialInfos pinCredentialInfo;
388     int32_t queryPinResult = DoQueryPinInfo(templateId, &pinCredentialInfo);
389     IF_TRUE_LOGE_AND_RETURN_VAL(queryPinResult != RESULT_SUCCESS, false);
390 
391     int32_t setResultCodeResult = SetAttributeInt32(attribute, ATTR_RESULT_CODE, resultCode);
392     IF_TRUE_LOGE_AND_RETURN_VAL(setResultCodeResult != RESULT_SUCCESS, false);
393 
394     int32_t setTemplateIdResult = SetAttributeUint64(attribute, ATTR_TEMPLATE_ID, templateId);
395     IF_TRUE_LOGE_AND_RETURN_VAL(setTemplateIdResult != RESULT_SUCCESS, false);
396 
397     int32_t setSubTypeResult = SetAttributeUint64(attribute, ATTR_PIN_SUB_TYPE, pinCredentialInfo.subType);
398     IF_TRUE_LOGE_AND_RETURN_VAL(setSubTypeResult != RESULT_SUCCESS, false);
399 
400     if (pinCredentialInfo.remainTimes > INT32_MAX) {
401         pinCredentialInfo.remainTimes = 0;
402     }
403     int32_t setRemainAttempts = SetAttributeInt32(
404         attribute, ATTR_REMAIN_ATTEMPTS, (int32_t)pinCredentialInfo.remainTimes);
405     IF_TRUE_LOGE_AND_RETURN_VAL(setRemainAttempts != RESULT_SUCCESS, false);
406 
407     if (pinCredentialInfo.freezeTime > INT32_MAX) {
408         pinCredentialInfo.freezeTime = INT32_MAX;
409     }
410     int32_t setLockoutDuration = SetAttributeInt32(
411         attribute, ATTR_LOCKOUT_DURATION, (int32_t)pinCredentialInfo.freezeTime);
412     IF_TRUE_LOGE_AND_RETURN_VAL(setLockoutDuration != RESULT_SUCCESS, false);
413 
414     int32_t setAcl = SetAttributeUint32(attribute, ATTR_ACL, PIN_CAPABILITY_LEVEL);
415     IF_TRUE_LOGE_AND_RETURN_VAL(setAcl != RESULT_SUCCESS, false);
416 
417     if (rootSecret != NULL) {
418         int32_t setRootSecret = SetBufferToAttribute(attribute, ATTR_ROOT_SECRET, rootSecret);
419         IF_TRUE_LOGE_AND_RETURN_VAL(setRootSecret != RESULT_SUCCESS, false);
420     }
421 
422     return true;
423 }
424 
PinResultToFwkResult(int32_t pinResult)425 int32_t PinResultToFwkResult(int32_t pinResult)
426 {
427     switch (pinResult) {
428         case RESULT_SUCCESS:
429             return SUCCESS;
430         case RESULT_BAD_PARAM:
431             return INVALID_PARAMETERS;
432         case RESULT_COMPARE_FAIL:
433             return FAIL;
434         case RESULT_BUSY:
435             return BUSY;
436         case RESULT_PIN_FREEZE:
437             return LOCKED;
438         default:
439             return GENERAL_ERROR;
440     }
441 }
442