1 /*
2 * Copyright (c) 2022 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 "utils_tlv.h"
17
18 #include <stddef.h>
19
20 #include "securec.h"
21
22 #define TLV_TAG_LEN sizeof(uint16_t)
23 #define TLV_LENGTH_LEN sizeof(uint16_t)
24 #define TLV_TLV_HEAD_LEN (TLV_TAG_LEN + TLV_LENGTH_LEN)
25
GetNextTlv(const uint8_t * buffer)26 static uint8_t *GetNextTlv(const uint8_t *buffer)
27 {
28 return (uint8_t *)buffer + ((TlvCommon *)buffer)->len + TLV_TLV_HEAD_LEN;
29 }
30
ParseTlv(const uint8_t * buffer,TlvCommon * tlv,const uint8_t * boundary,uint32_t * retCode)31 static uint8_t *ParseTlv(const uint8_t *buffer, TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
32 {
33 if (buffer + TLV_TLV_HEAD_LEN > boundary) {
34 *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
35 return NULL;
36 }
37 if (GetNextTlv(buffer) > boundary) {
38 *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
39 return NULL;
40 }
41 tlv->tag = ((TlvCommon *)buffer)->tag;
42 tlv->len = ((TlvCommon *)buffer)->len;
43 tlv->value = (uint8_t *)buffer + TLV_TLV_HEAD_LEN;
44 *retCode = TLV_OK;
45 return GetNextTlv(buffer);
46 }
47
AppendTlv(uint8_t * buffer,const TlvCommon * tlv,const uint8_t * boundary,uint32_t * retCode)48 static uint8_t *AppendTlv(uint8_t *buffer, const TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
49 {
50 if (buffer > boundary) {
51 *retCode = TLV_ERR_BUFF_NO_ENOUGH;
52 return NULL;
53 }
54 if (buffer + ((TlvCommon *)tlv)->len + TLV_TLV_HEAD_LEN > boundary) {
55 *retCode = TLV_ERR_BUFF_NO_ENOUGH;
56 return NULL;
57 }
58 ((TlvCommon *)buffer)->tag = tlv->tag;
59 ((TlvCommon *)buffer)->len = tlv->len;
60 if (tlv->len != 0 && tlv->value != NULL) {
61 if (memcpy_s(buffer + TLV_TLV_HEAD_LEN, boundary - buffer - TLV_TLV_HEAD_LEN, tlv->value, tlv->len) != EOK) {
62 *retCode = TLV_ERR_BUFF_NO_ENOUGH;
63 return NULL;
64 }
65 }
66 *retCode = TLV_OK;
67 return GetNextTlv(buffer);
68 }
69
Serialize(const TlvCommon * tlv,uint32_t tlvCount,uint8_t * buff,uint32_t maxBuffSize,uint32_t * buffSize)70 uint32_t Serialize(const TlvCommon *tlv, uint32_t tlvCount, uint8_t *buff, uint32_t maxBuffSize, uint32_t *buffSize)
71 {
72 if (tlv == NULL || buff == NULL || buffSize == NULL) {
73 return TLV_ERR_INVALID_PARA;
74 }
75
76 uint8_t *curr = buff;
77 uint8_t *boundary = buff + maxBuffSize;
78
79 uint32_t retCode = TLV_OK;
80 for (uint32_t index = 0; index < tlvCount; index++) {
81 curr = AppendTlv(curr, &tlv[index], boundary, &retCode);
82 if (curr == NULL || retCode != TLV_OK) {
83 return retCode;
84 }
85 }
86 *buffSize = curr - buff;
87 return TLV_OK;
88 }
89
Deserialize(const uint8_t * buff,uint32_t buffSize,TlvCommon * tlv,uint32_t maxTlvCount,uint32_t * tlvCount)90 uint32_t Deserialize(const uint8_t *buff, uint32_t buffSize, TlvCommon *tlv, uint32_t maxTlvCount, uint32_t *tlvCount)
91 {
92 if (buff == NULL || tlv == NULL || tlvCount == NULL) {
93 return TLV_ERR_INVALID_PARA;
94 }
95
96 uint8_t *msg = (uint8_t *)buff;
97 const uint8_t *boundary = buff + buffSize;
98 uint32_t index = 0;
99
100 while (msg != NULL) {
101 if (index >= maxTlvCount) {
102 return TLV_ERR_BUFF_NO_ENOUGH;
103 }
104 uint32_t retCode = TLV_OK;
105 msg = ParseTlv(msg, &tlv[index], boundary, &retCode);
106 if (msg == NULL || retCode != TLV_OK) {
107 break;
108 }
109 index++;
110 }
111
112 *tlvCount = index;
113 return TLV_OK;
114 }
115