1/*
2 * Copyright (C) 2023-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 "attribute.h"
17
18#include "securec.h"
19
20#include "adaptor_log.h"
21#include "adaptor_memory.h"
22
23#ifdef IAM_TEST_ENABLE
24#define IAM_STATIC
25#else
26#define IAM_STATIC static
27#endif
28
29#define SUCCESS RESULT_SUCCESS
30#define GENERAL_ERROR RESULT_GENERAL_ERROR
31#define INVALID_PARAMETERS RESULT_BAD_PARAM
32
33AttributeKey g_attributeKeyArray[] = {
34    ATTR_RESULT_CODE,
35    ATTR_SIGNATURE,
36    ATTR_IDENTIFY_MODE,
37    ATTR_TEMPLATE_ID,
38    ATTR_TEMPLATE_ID_LIST,
39    ATTR_REMAIN_ATTEMPTS,
40    ATTR_LOCKOUT_DURATION,
41    ATTR_SCHEDULE_ID,
42    ATTR_DATA,
43    ATTR_PIN_SUB_TYPE,
44    ATTR_SCHEDULE_MODE,
45    ATTR_PROPERTY_MODE,
46    ATTR_TYPE,
47    ATTR_CREDENTIAL_ID,
48    ATTR_CONTROLLER,
49    ATTR_CALLER_UID,
50    ATTR_RESULT,
51    ATTR_CAPABILITY_LEVEL,
52    ATTR_ALGORITHM_INFO,
53    ATTR_TIME_STAMP,
54    ATTR_ROOT_SECRET,
55    ATTR_ROOT,
56    ATTR_ATTRS,
57    ATTR_EXECUTOR_INDEX,
58    ATTR_PUBLIC_KEY,
59    ATTR_EXECUTOR_MATCHER,
60    ATTR_LOCAL_UDID,
61    ATTR_PEER_UDID,
62    ATTR_LOCKOUT_DURATION,
63    ATTR_REMAIN_ATTEMPTS,
64    ATTR_USER_ID,
65    ATTR_TOKEN,
66    ATTR_EXECUTOR_ROLE,
67    ATTR_ESL,
68    ATTR_VERIFIER_UDID,
69    ATTR_COLLECTOR_UDID,
70    ATTR_CHALLENGE,
71    ATTR_EXPIRED_SYS_TIME,
72};
73
74#define ARRAY_LENGTH(array) (uint32_t)(sizeof(array) / sizeof((array)[0]))
75#define ATTRIBUTE_LEN (ARRAY_LENGTH(g_attributeKeyArray))
76
77typedef struct {
78    Uint8Array *values[ATTRIBUTE_LEN];
79} AttributeImpl;
80
81IAM_STATIC uint32_t Ntohl32(uint32_t in)
82{
83    return in;
84}
85
86IAM_STATIC uint32_t Htonl32(uint32_t in)
87{
88    return in;
89}
90
91IAM_STATIC uint64_t Ntohl64(uint64_t in)
92{
93    return in;
94}
95
96IAM_STATIC uint64_t Htonl64(uint64_t in)
97{
98    return in;
99}
100
101IAM_STATIC void Ntohl64Array(Uint64Array *array)
102{
103    for (uint32_t i = 0; i < array->len; i++) {
104        array->data[i] = Ntohl64(array->data[i]);
105    }
106}
107
108IAM_STATIC void Htonl64Array(Uint64Array *array)
109{
110    for (uint32_t i = 0; i < array->len; i++) {
111        array->data[i] = Htonl64(array->data[i]);
112    }
113}
114
115IAM_STATIC ResultCode GetAttributeIndex(AttributeKey key, uint32_t *index)
116{
117    for (uint32_t i = 0; i < ATTRIBUTE_LEN; ++i) {
118        if (g_attributeKeyArray[i] == key) {
119            *index = i;
120            return SUCCESS;
121        }
122    }
123
124    return GENERAL_ERROR;
125}
126
127IAM_STATIC ResultCode ReadDataFromMsg(const Uint8Array msg, uint32_t *readIndex, Uint8Array *retData)
128{
129    if (msg.len <= *readIndex) {
130        LOG_ERROR("msg length is not enough");
131        return GENERAL_ERROR;
132    }
133
134    if (msg.len - *readIndex < retData->len) {
135        LOG_ERROR("remain data length is not enough");
136        return GENERAL_ERROR;
137    }
138
139    if (memcpy_s(retData->data, retData->len, msg.data + *readIndex, retData->len) != EOK) {
140        LOG_ERROR("memcpy_s fail");
141        return GENERAL_ERROR;
142    }
143
144    *readIndex += retData->len;
145    return SUCCESS;
146}
147
148IAM_STATIC ResultCode ReadUint32FromMsg(const Uint8Array msg, uint32_t *readIndex, uint32_t *retValue)
149{
150    uint32_t netOrderValue;
151    Uint8Array uint8Data = { (uint8_t *)&netOrderValue, sizeof(netOrderValue) };
152    ResultCode result = ReadDataFromMsg(msg, readIndex, &uint8Data);
153    if (result != SUCCESS) {
154        LOG_ERROR("read data fail");
155        return GENERAL_ERROR;
156    }
157
158    *retValue = Ntohl32(netOrderValue);
159    return SUCCESS;
160}
161
162IAM_STATIC ResultCode WriteDataToMsg(Uint8Array *msg, uint32_t *writeIndex, const Uint8Array data)
163{
164    if (msg->len <= *writeIndex) {
165        LOG_ERROR("msg length is not enough");
166        return GENERAL_ERROR;
167    }
168
169    if (msg->len - *writeIndex < data.len) {
170        LOG_ERROR("remain data size is not enough");
171        return GENERAL_ERROR;
172    }
173
174    if (memcpy_s(msg->data + *writeIndex, msg->len - *writeIndex, data.data, data.len) != EOK) {
175        LOG_ERROR("memcpy_s fail");
176        return GENERAL_ERROR;
177    }
178
179    *writeIndex += data.len;
180    return SUCCESS;
181}
182
183IAM_STATIC ResultCode WriteUInt32ToMsg(Uint8Array *msg, uint32_t *writeIndex, uint32_t value)
184{
185    uint32_t netOrderValue = Htonl32(value);
186    ResultCode result =
187        WriteDataToMsg(msg, writeIndex, (Uint8Array){ (uint8_t *)&netOrderValue, sizeof(netOrderValue) });
188    if (result != SUCCESS) {
189        LOG_ERROR("write data fail");
190        return GENERAL_ERROR;
191    }
192    return SUCCESS;
193}
194
195IAM_STATIC ResultCode ParseAttributeSerializedMsgInner(Attribute *attribute, const Uint8Array msg,
196    const Uint8Array *readBuffer)
197{
198    uint32_t readIndex = 0;
199    while (readIndex < msg.len) {
200        uint32_t type;
201        ResultCode readTypeResult = ReadUint32FromMsg(msg, &readIndex, &type);
202        IF_TRUE_LOGE_AND_RETURN_VAL(readTypeResult != SUCCESS, GENERAL_ERROR);
203
204        uint32_t length;
205        ResultCode readLengthResult = ReadUint32FromMsg(msg, &readIndex, &length);
206        IF_TRUE_LOGE_AND_RETURN_VAL(readLengthResult != SUCCESS, GENERAL_ERROR);
207        IF_TRUE_LOGE_AND_RETURN_VAL(length > readBuffer->len, GENERAL_ERROR);
208
209        Uint8Array readData = { readBuffer->data, length };
210        if (length > 0) {
211            ResultCode readDataResult = ReadDataFromMsg(msg, &readIndex, &readData);
212            IF_TRUE_LOGE_AND_RETURN_VAL(readDataResult != SUCCESS, GENERAL_ERROR);
213        }
214
215        ResultCode setAttrResult = SetAttributeUint8Array(attribute, type, readData);
216        IF_TRUE_LOGE_AND_RETURN_VAL(setAttrResult != SUCCESS, GENERAL_ERROR);
217    }
218
219    return SUCCESS;
220}
221
222IAM_STATIC ResultCode ParseAttributeSerializedMsg(Attribute *attribute, const Uint8Array msg)
223{
224    Uint8Array *readBuffer = CreateUint8ArrayBySize(MAX_EXECUTOR_MSG_LEN);
225    IF_TRUE_LOGE_AND_RETURN_VAL(readBuffer == NULL, GENERAL_ERROR);
226
227    ResultCode result = ParseAttributeSerializedMsgInner(attribute, msg, readBuffer);
228    if (result != SUCCESS) {
229        LOG_ERROR("ParseAttributeSerializedMsgInner fail");
230    }
231    DestroyUint8Array(&readBuffer);
232
233    return result;
234}
235
236ResultCode ParseMultiDataSerializedMsg(const Uint8Array msg, Uint8Array *subMsgData, int *subMsgSize)
237{
238    IF_TRUE_LOGE_AND_RETURN_VAL(subMsgSize == NULL, GENERAL_ERROR);
239    IF_TRUE_LOGE_AND_RETURN_VAL(subMsgData == NULL, GENERAL_ERROR);
240
241    uint32_t readIndex = 0;
242    uint32_t subMsgIndex = 0;
243    while (readIndex < msg.len) {
244        uint32_t length;
245        ResultCode readLengthResult = ReadUint32FromMsg(msg, &readIndex, &length);
246        IF_TRUE_LOGE_AND_RETURN_VAL(readLengthResult != SUCCESS, GENERAL_ERROR);
247
248        if (length > 0) {
249            IF_TRUE_LOGE_AND_RETURN_VAL(subMsgIndex >= *subMsgSize, GENERAL_ERROR);
250            // subMsgData is freed in outer function
251            subMsgData[subMsgIndex] = (Uint8Array){ Malloc(length), length };
252            IF_TRUE_LOGE_AND_RETURN_VAL(subMsgData[subMsgIndex].data == NULL, GENERAL_ERROR);
253            ResultCode readDataResult = ReadDataFromMsg(msg, &readIndex, &subMsgData[subMsgIndex]);
254            IF_TRUE_LOGE_AND_RETURN_VAL(readDataResult != SUCCESS, GENERAL_ERROR);
255            subMsgIndex++;
256        }
257    }
258
259    *subMsgSize = subMsgIndex;
260    return SUCCESS;
261}
262
263Attribute *CreateEmptyAttribute(void)
264{
265    AttributeImpl *attribute = Malloc(sizeof(AttributeImpl));
266    IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, NULL);
267    (void)memset_s(attribute, sizeof(AttributeImpl), 0, sizeof(AttributeImpl));
268
269    return attribute;
270}
271
272Attribute *CreateAttributeFromSerializedMsg(const Uint8Array msg)
273{
274    IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(msg), NULL);
275
276    Attribute *attribute = CreateEmptyAttribute();
277    if (attribute == NULL) {
278        LOG_ERROR("CreateEmptyAttribute failed");
279        return NULL;
280    }
281
282    ResultCode result = ParseAttributeSerializedMsg(attribute, msg);
283    if (result != SUCCESS) {
284        LOG_ERROR("ParseAttributeSerializedMsg failed");
285        FreeAttribute((Attribute **)&attribute);
286        return NULL;
287    }
288
289    return attribute;
290}
291
292ResultCode GetAttributeSerializedMsg(const Attribute *attributePublic, Uint8Array *retMsg)
293{
294    IF_TRUE_LOGE_AND_RETURN_VAL(attributePublic == NULL, INVALID_PARAMETERS);
295    IF_TRUE_LOGE_AND_RETURN_VAL(retMsg == NULL, INVALID_PARAMETERS);
296    IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(*retMsg), INVALID_PARAMETERS);
297
298    const AttributeImpl *attribute = (const AttributeImpl *)attributePublic;
299    uint32_t writeIndex = 0;
300    for (uint32_t i = 0; i < ATTRIBUTE_LEN; i++) {
301        Uint8Array *array = attribute->values[i];
302        if (array == NULL) {
303            continue;
304        }
305
306        ResultCode writeTypeResult = WriteUInt32ToMsg(retMsg, &writeIndex, g_attributeKeyArray[i]);
307        IF_TRUE_LOGE_AND_RETURN_VAL(writeTypeResult != SUCCESS, GENERAL_ERROR);
308
309        ResultCode writeLengthResult = WriteUInt32ToMsg(retMsg, &writeIndex, array->len);
310        IF_TRUE_LOGE_AND_RETURN_VAL(writeLengthResult != SUCCESS, GENERAL_ERROR);
311
312        if (array->len == 0) {
313            continue;
314        }
315        ResultCode writeDataResult =
316            WriteDataToMsg(retMsg, &writeIndex, *array);
317        IF_TRUE_LOGE_AND_RETURN_VAL(writeDataResult != SUCCESS, GENERAL_ERROR);
318    }
319
320    retMsg->len = writeIndex;
321    return SUCCESS;
322}
323
324void FreeAttribute(Attribute **attribute)
325{
326    IF_TRUE_LOGE_AND_RETURN(attribute == NULL);
327    IF_TRUE_LOGE_AND_RETURN(*attribute == NULL);
328    AttributeImpl *impl = (AttributeImpl *)*attribute;
329    for (uint32_t i = 0; i < ATTRIBUTE_LEN; ++i) {
330        DestroyUint8Array(&impl->values[i]);
331    }
332
333    IAM_FREE_AND_SET_NULL(*attribute);
334}
335
336ResultCode GetAttributeUint32(const Attribute *attribute, AttributeKey key, uint32_t *value)
337{
338    IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS);
339    IF_TRUE_LOGE_AND_RETURN_VAL(value == NULL, INVALID_PARAMETERS);
340
341    uint32_t netOrderValue;
342    Uint8Array uint32Data = { (uint8_t *)&netOrderValue, sizeof(netOrderValue) };
343    ResultCode getAttrResult = GetAttributeUint8Array(attribute, key, &uint32Data);
344    IF_TRUE_LOGE_AND_RETURN_VAL(getAttrResult != SUCCESS, GENERAL_ERROR);
345    IF_TRUE_LOGE_AND_RETURN_VAL(uint32Data.len != sizeof(netOrderValue), GENERAL_ERROR);
346
347    *value = Ntohl32(netOrderValue);
348    return SUCCESS;
349}
350
351ResultCode SetAttributeUint32(Attribute *attribute, AttributeKey key, const uint32_t value)
352{
353    IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS);
354
355    uint32_t netOrderValue = Htonl32(value);
356    ResultCode result =
357        SetAttributeUint8Array(attribute, key, (Uint8Array) { (uint8_t *)&netOrderValue, sizeof(netOrderValue) });
358    IF_TRUE_LOGE_AND_RETURN_VAL(result != SUCCESS, GENERAL_ERROR);
359
360    return result;
361}
362
363ResultCode GetAttributeInt32(const Attribute *attribute, AttributeKey key, int32_t *retValue)
364{
365    IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS);
366    IF_TRUE_LOGE_AND_RETURN_VAL(retValue == NULL, INVALID_PARAMETERS);
367
368    return GetAttributeUint32(attribute, key, (uint32_t *)retValue);
369}
370
371ResultCode SetAttributeInt32(Attribute *attribute, AttributeKey key, const int32_t value)
372{
373    IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS);
374
375    return SetAttributeUint32(attribute, key, (uint32_t)value);
376}
377
378ResultCode GetAttributeUint64(const Attribute *attribute, AttributeKey key, uint64_t *retValue)
379{
380    IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS);
381    IF_TRUE_LOGE_AND_RETURN_VAL(retValue == NULL, INVALID_PARAMETERS);
382
383    uint64_t netOrderValue;
384    Uint8Array uint64Data = { (uint8_t *)&netOrderValue, sizeof(netOrderValue) };
385    ResultCode getAttrResult = GetAttributeUint8Array(attribute, key, &uint64Data);
386    IF_TRUE_LOGE_AND_RETURN_VAL(getAttrResult != SUCCESS, GENERAL_ERROR);
387    IF_TRUE_LOGE_AND_RETURN_VAL(uint64Data.len != sizeof(netOrderValue), GENERAL_ERROR);
388
389    *retValue = Ntohl64(netOrderValue);
390    return SUCCESS;
391}
392
393ResultCode SetAttributeUint64(Attribute *attribute, AttributeKey key, const uint64_t value)
394{
395    IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS);
396
397    uint64_t netOrderValue = Htonl64(value);
398    ResultCode setAttrResult =
399        SetAttributeUint8Array(attribute, key, (Uint8Array){ (uint8_t *)&netOrderValue, sizeof(netOrderValue) });
400    IF_TRUE_LOGE_AND_RETURN_VAL(setAttrResult != SUCCESS, GENERAL_ERROR);
401
402    return SUCCESS;
403}
404
405ResultCode GetAttributeUint8Array(const Attribute *attributePub, AttributeKey key, Uint8Array *retData)
406{
407    IF_TRUE_LOGE_AND_RETURN_VAL(attributePub == NULL, INVALID_PARAMETERS);
408    IF_TRUE_LOGE_AND_RETURN_VAL(retData == NULL, INVALID_PARAMETERS);
409    IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(*retData), INVALID_PARAMETERS);
410
411    const AttributeImpl *attribute = (const AttributeImpl *)attributePub;
412
413    uint32_t attributeIndex;
414    ResultCode getAttrIndexResult = GetAttributeIndex(key, &attributeIndex);
415    IF_TRUE_LOGE_AND_RETURN_VAL(getAttrIndexResult != SUCCESS, GENERAL_ERROR);
416
417    if (attribute->values[attributeIndex] == NULL) {
418        LOG_ERROR("data is not set");
419        return GENERAL_ERROR;
420    }
421
422    if (attribute->values[attributeIndex]->data != NULL && attribute->values[attributeIndex]->len != 0) {
423        errno_t memcpyRet = memcpy_s(retData->data, retData->len, attribute->values[attributeIndex]->data,
424            attribute->values[attributeIndex]->len);
425        IF_TRUE_LOGE_AND_RETURN_VAL(memcpyRet != EOK, GENERAL_ERROR);
426    } else {
427        LOG_INFO("the current data is an empty array");
428    }
429    retData->len = attribute->values[attributeIndex]->len;
430
431    return SUCCESS;
432}
433
434ResultCode SetAttributeUint8Array(Attribute *attributePub, AttributeKey key, const Uint8Array data)
435{
436    IF_TRUE_LOGE_AND_RETURN_VAL(attributePub == NULL, INVALID_PARAMETERS);
437    IF_TRUE_LOGE_AND_RETURN_VAL(!IS_ARRAY_VALID(data), INVALID_PARAMETERS);
438
439    AttributeImpl *attribute = (AttributeImpl *)attributePub;
440
441    uint32_t attributeIndex;
442    ResultCode getAttrIndexResult = GetAttributeIndex(key, &attributeIndex);
443    IF_TRUE_LOGE_AND_RETURN_VAL(getAttrIndexResult != SUCCESS, GENERAL_ERROR);
444
445    DestroyUint8Array(&attribute->values[attributeIndex]);
446    attribute->values[attributeIndex] = CreateUint8ArrayByData(data.data, data.len);
447    if (attribute->values[attributeIndex] == NULL) {
448        LOG_ERROR("CreateUint8ArrayByData fail");
449        return GENERAL_ERROR;
450    }
451
452    return SUCCESS;
453}
454
455ResultCode GetAttributeUint64Array(const Attribute *attribute, AttributeKey key, Uint64Array *retData)
456{
457    IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS);
458    IF_TRUE_LOGE_AND_RETURN_VAL(retData == NULL, INVALID_PARAMETERS);
459    IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(*retData), INVALID_PARAMETERS);
460
461    Uint8Array uint64ArrayData = { (uint8_t *)retData->data, retData->len * sizeof(uint64_t) };
462    ResultCode getAttrResult = GetAttributeUint8Array(attribute, key, &uint64ArrayData);
463    IF_TRUE_LOGE_AND_RETURN_VAL(getAttrResult != SUCCESS, GENERAL_ERROR);
464    if (uint64ArrayData.len % sizeof(uint64_t) != 0) {
465        LOG_ERROR("uint8 length %u is incorrect", uint64ArrayData.len);
466        return GENERAL_ERROR;
467    }
468    Ntohl64Array(retData);
469
470    retData->len = uint64ArrayData.len / sizeof(uint64_t);
471    return SUCCESS;
472}
473
474ResultCode SetAttributeUint64Array(Attribute *attribute, AttributeKey key, const Uint64Array data)
475{
476    IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS);
477    IF_TRUE_LOGE_AND_RETURN_VAL(!IS_ARRAY_VALID(data), INVALID_PARAMETERS);
478
479    Uint64Array *netOrderData = CreateUint64ArrayByData(data.data, data.len);
480    IF_TRUE_LOGE_AND_RETURN_VAL(netOrderData == NULL, GENERAL_ERROR);
481
482    ResultCode result = GENERAL_ERROR;
483    do {
484        Htonl64Array(netOrderData);
485        if (netOrderData->len > UINT32_MAX / sizeof(uint64_t)) {
486            LOG_ERROR("netOrderData->len is invalid");
487            break;
488        }
489        result = SetAttributeUint8Array(attribute, key,
490            (Uint8Array) { (uint8_t *)netOrderData->data, netOrderData->len * sizeof(uint64_t) });
491        if (result != SUCCESS) {
492            LOG_ERROR("SetAttributeUint8Array fail");
493            break;
494        }
495    } while (0);
496
497    DestroyUint64Array(&netOrderData);
498    return result;
499}
500
501ResultCode GetMultiDataSerializedMsg(Uint8Array *sourceArrayMsg, uint32_t size, Uint8Array *retMsg)
502{
503    IF_TRUE_LOGE_AND_RETURN_VAL(sourceArrayMsg == NULL, INVALID_PARAMETERS);
504    IF_TRUE_LOGE_AND_RETURN_VAL(retMsg == NULL, INVALID_PARAMETERS);
505    IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(*retMsg), INVALID_PARAMETERS);
506
507    uint32_t writeIndex = 0;
508    for (uint32_t i = 0; i < size; i++) {
509        IF_TRUE_LOGE_AND_RETURN_VAL(sourceArrayMsg[i].data == NULL, GENERAL_ERROR);
510        Uint8Array sourceMsg = sourceArrayMsg[i];
511        if (sourceMsg.len == 0) {
512            continue;
513        }
514        ResultCode writeLengthResult = WriteUInt32ToMsg(retMsg, &writeIndex, sourceMsg.len);
515        IF_TRUE_LOGE_AND_RETURN_VAL(writeLengthResult != SUCCESS, GENERAL_ERROR);
516
517        ResultCode writeDataResult = WriteDataToMsg(retMsg, &writeIndex, sourceMsg);
518        IF_TRUE_LOGE_AND_RETURN_VAL(writeDataResult != SUCCESS, GENERAL_ERROR);
519    }
520    retMsg->len = writeIndex;
521    return SUCCESS;
522}
523