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