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 "tlv_wrapper.h"
17
18 #include <string.h>
19
20 #include "securec.h"
21
22 #include "adaptor_log.h"
23 #include "adaptor_memory.h"
24
PutTlvObject(TlvListNode * head,int32_t type,uint32_t length,const void * value)25 static int32_t PutTlvObject(TlvListNode *head, int32_t type, uint32_t length, const void *value)
26 {
27 if ((head == NULL) || (value == NULL) || (length > MAX_BUFFER_SIZE)) {
28 return PARAM_ERR;
29 }
30
31 TlvType *tlv = (TlvType *)Malloc(sizeof(TlvType));
32 if (tlv == NULL) {
33 return MALLOC_FAIL;
34 }
35
36 tlv->type = type;
37 tlv->length = length;
38 tlv->value = NULL;
39 if (length > 0) {
40 tlv->value = (uint8_t *)Malloc(length);
41 if (tlv->value == NULL) {
42 Free(tlv);
43 tlv = NULL;
44 return MALLOC_FAIL;
45 }
46
47 if (memcpy_s(tlv->value, length, value, length) != EOK) {
48 Free(tlv->value);
49 tlv->value = NULL;
50 Free(tlv);
51 tlv = NULL;
52 return MEMCPY_ERR;
53 }
54 }
55
56 TlvObject object;
57 object.value = tlv;
58 int32_t ret = AddTlvNode(head, &object);
59 if (ret != OPERA_SUCC) {
60 if (object.value != NULL) {
61 Free(object.value->value);
62 object.value->value = NULL;
63 Free(object.value);
64 object.value = NULL;
65 }
66 }
67 return ret;
68 }
69
ParseGetHeadTag(const TlvListNode * node,int32_t * tag)70 int32_t ParseGetHeadTag(const TlvListNode *node, int32_t *tag)
71 {
72 if (node == NULL || tag == NULL) {
73 return PARAM_ERR;
74 }
75 TlvType *tlv = node->data.value;
76 if (tlv == NULL) {
77 return TAG_NOT_EXIST;
78 }
79 *tag = tlv->type;
80 return OPERA_SUCC;
81 }
82
ParseTlvWrapper(const uint8_t * buffer,uint32_t bufferSize,TlvListNode * head)83 int32_t ParseTlvWrapper(const uint8_t *buffer, uint32_t bufferSize, TlvListNode *head)
84 {
85 if (buffer == NULL || bufferSize == 0 || bufferSize > MAX_BUFFER_SIZE || head == NULL) {
86 return PARAM_ERR;
87 }
88
89 uint32_t offset = 0;
90 while (offset < bufferSize) {
91 if ((bufferSize - offset) < TLV_HEADER_LEN) {
92 LOG_ERROR("bufferSize = %{public}u, offset = %{public}u", bufferSize, offset);
93 return OPERA_FAIL;
94 }
95 int32_t type = (int32_t)Ntohl(*(int32_t *)(buffer + offset));
96 offset += sizeof(int32_t);
97 uint32_t length = Ntohl(*(int32_t *)(buffer + offset));
98 offset += sizeof(int32_t);
99 if (length > (bufferSize - offset)) {
100 LOG_ERROR("bufferSize = %{public}u, offset = %{public}u, length = %{public}u", bufferSize, offset, length);
101 return OPERA_FAIL;
102 }
103 int32_t ret = PutTlvObject(head, type, length, buffer + offset);
104 if (ret != OPERA_SUCC) {
105 return ret;
106 }
107 offset += length;
108 }
109
110 return OPERA_SUCC;
111 }
112
GetTlvValue(TlvListNode * node,int32_t msgType,uint32_t * len)113 static uint8_t *GetTlvValue(TlvListNode *node, int32_t msgType, uint32_t *len)
114 {
115 if ((node == NULL) || (len == NULL)) {
116 LOG_ERROR("GetTlvValue input invalid");
117 return NULL;
118 }
119 TlvType *tlv = node->data.value;
120 if (tlv == NULL) {
121 LOG_ERROR("GetTlvValue tlv is NULL");
122 return NULL;
123 }
124 int32_t type = tlv->type;
125 *len = tlv->length;
126 if ((type != msgType) || (*len == 0)) {
127 LOG_ERROR("GetTlvValue return type = %d, len = %u, msgType = %d", type, *len, msgType);
128 return NULL;
129 }
130
131 return tlv->value;
132 }
133
ParseUint64Para(TlvListNode * node,int32_t msgType,uint64_t * retVal)134 int32_t ParseUint64Para(TlvListNode *node, int32_t msgType, uint64_t *retVal)
135 {
136 if ((node == NULL) || (retVal == NULL)) {
137 LOG_ERROR("ParseUint64Para parameter check failed");
138 return PARAM_ERR;
139 }
140 uint32_t len = 0;
141 uint8_t *val = GetTlvValue(node, msgType, &len);
142 if ((val == NULL) || (len != sizeof(uint64_t))) {
143 LOG_ERROR("ParseUint64Para GetTlvValue failed");
144 return OPERA_FAIL;
145 }
146 *retVal = Ntohll(*(uint64_t *)val);
147 return OPERA_SUCC;
148 }
149
ParseInt64Para(TlvListNode * node,int32_t msgType,int64_t * retVal)150 int32_t ParseInt64Para(TlvListNode *node, int32_t msgType, int64_t *retVal)
151 {
152 if ((node == NULL) || (retVal == NULL)) {
153 LOG_ERROR("ParseInt64Para parameter check failed");
154 return PARAM_ERR;
155 }
156 uint32_t len = 0;
157 uint8_t *val = GetTlvValue(node, msgType, &len);
158 if ((val == NULL) || (len != sizeof(int64_t))) {
159 LOG_ERROR("ParseInt64Para GetTlvValue failed");
160 return OPERA_FAIL;
161 }
162 *retVal = (int64_t)Ntohll(*(uint64_t *)val);
163 return OPERA_SUCC;
164 }
165
ParseUint32Para(TlvListNode * node,int32_t msgType,uint32_t * retVal)166 int32_t ParseUint32Para(TlvListNode *node, int32_t msgType, uint32_t *retVal)
167 {
168 if ((node == NULL) || (retVal == NULL)) {
169 LOG_ERROR("ParseUint32Para parameter check failed");
170 return PARAM_ERR;
171 }
172 uint32_t len = 0;
173 uint8_t *val = GetTlvValue(node, msgType, &len);
174 if ((val == NULL) || (len != sizeof(uint32_t))) {
175 LOG_ERROR("ParseUint32Para GetTlvValue failed");
176 return OPERA_FAIL;
177 }
178 *retVal = Ntohl(*(uint32_t *)val);
179 return OPERA_SUCC;
180 }
181
ParseInt32Para(TlvListNode * node,int32_t msgType,int32_t * retVal)182 int32_t ParseInt32Para(TlvListNode *node, int32_t msgType, int32_t *retVal)
183 {
184 if ((node == NULL) || (retVal == NULL)) {
185 LOG_ERROR("ParseInt32Para parameter check failed");
186 return PARAM_ERR;
187 }
188 uint32_t len = 0;
189 uint8_t *val = GetTlvValue(node, msgType, &len);
190 if ((val == NULL) || (len != sizeof(int32_t))) {
191 LOG_ERROR("ParseInt32Para GetTlvValue failed");
192 return OPERA_FAIL;
193 }
194 *retVal = (int32_t)Ntohl(*(uint32_t *)val);
195 return OPERA_SUCC;
196 }
197
ParseBuffPara(TlvListNode * node,int32_t msgType)198 Buffer *ParseBuffPara(TlvListNode *node, int32_t msgType)
199 {
200 if (node == NULL) {
201 LOG_ERROR("ParseBuffPara parameter check failed");
202 return NULL;
203 }
204 uint32_t len = 0;
205 uint8_t *val = GetTlvValue(node, msgType, &len);
206 if (val == NULL) {
207 LOG_ERROR("ParseBuffPara GetTlvValue failed");
208 return NULL;
209 }
210 Buffer *buff = CreateBufferByData(val, len);
211 if (buff == NULL) {
212 LOG_ERROR("ParseBuffPara CreateBufferByData failed");
213 return NULL;
214 }
215 return buff;
216 }
217
ParseUint8Para(TlvListNode * node,int32_t msgType,uint8_t * retVal)218 int32_t ParseUint8Para(TlvListNode *node, int32_t msgType, uint8_t *retVal)
219 {
220 if ((node == NULL) || (retVal == NULL)) {
221 LOG_ERROR("ParseUint8Para parameter check failed");
222 return PARAM_ERR;
223 }
224 uint32_t len = 0;
225 uint8_t *val = GetTlvValue(node, msgType, &len);
226 if ((val == NULL) || (len != sizeof(uint8_t))) {
227 LOG_ERROR("ParseUint8Para GetTlvValue failed");
228 return PARAM_ERR;
229 }
230 *retVal = *val;
231 return OPERA_SUCC;
232 }
233
GetUint64Para(TlvListNode * head,int32_t msgType,uint64_t * retVal)234 int32_t GetUint64Para(TlvListNode *head, int32_t msgType, uint64_t *retVal)
235 {
236 if ((head == NULL) || (retVal == NULL)) {
237 LOG_ERROR("GetUint64Para parameter check failed");
238 return PARAM_ERR;
239 }
240 TlvListNode *node = head;
241 while (node != NULL) {
242 int32_t nodeType;
243 int32_t ret = ParseGetHeadTag(node, &nodeType);
244 if (ret != OPERA_SUCC) {
245 return ret;
246 }
247 if (nodeType == msgType) {
248 return ParseUint64Para(node, msgType, retVal);
249 }
250 node = node->next;
251 }
252 return PARAM_ERR;
253 }
254
GetUint32Para(TlvListNode * head,int32_t msgType,uint32_t * retVal)255 int32_t GetUint32Para(TlvListNode *head, int32_t msgType, uint32_t *retVal)
256 {
257 if ((head == NULL) || (retVal == NULL)) {
258 LOG_ERROR("GetUint32Para parameter check failed");
259 return PARAM_ERR;
260 }
261 TlvListNode *node = head;
262 while (node != NULL) {
263 int32_t nodeType;
264 int32_t ret = ParseGetHeadTag(node, &nodeType);
265 if (ret != OPERA_SUCC) {
266 return ret;
267 }
268 if (nodeType == msgType) {
269 return ParseUint32Para(node, msgType, retVal);
270 }
271 node = node->next;
272 }
273 return PARAM_ERR;
274 }
275
GetInt32Para(TlvListNode * head,int32_t msgType,int32_t * retVal)276 int32_t GetInt32Para(TlvListNode *head, int32_t msgType, int32_t *retVal)
277 {
278 if ((head == NULL) || (retVal == NULL)) {
279 LOG_ERROR("GetInt32Para parameter check failed");
280 return PARAM_ERR;
281 }
282 TlvListNode *node = head;
283 while (node != NULL) {
284 int32_t nodeType;
285 int32_t ret = ParseGetHeadTag(node, &nodeType);
286 if (ret != OPERA_SUCC) {
287 return ret;
288 }
289 if (nodeType == msgType) {
290 return ParseInt32Para(node, msgType, retVal);
291 }
292 node = node->next;
293 }
294 return PARAM_ERR;
295 }
296
GetBuffPara(TlvListNode * head,int32_t msgType)297 Buffer *GetBuffPara(TlvListNode *head, int32_t msgType)
298 {
299 if (head == NULL) {
300 LOG_ERROR("GetBuffPara parameter check failed");
301 return NULL;
302 }
303 TlvListNode *node = head;
304 while (node != NULL) {
305 int32_t nodeType;
306 int32_t ret = ParseGetHeadTag(node, &nodeType);
307 if (ret != OPERA_SUCC) {
308 return NULL;
309 }
310 if (nodeType == msgType) {
311 return ParseBuffPara(node, msgType);
312 }
313 node = node->next;
314 }
315 return NULL;
316 }
317
TlvAppendObject(TlvListNode * head,int32_t type,const uint8_t * buffer,uint32_t length)318 int32_t TlvAppendObject(TlvListNode *head, int32_t type, const uint8_t *buffer, uint32_t length)
319 {
320 if (head == NULL || buffer == NULL || length == 0 || length > MAX_BUFFER_SIZE) {
321 LOG_ERROR("param is invalid");
322 return PARAM_ERR;
323 }
324 return PutTlvObject(head, type, length, buffer);
325 }
326
SerializeTlvWrapper(TlvListNode * head,uint8_t * buffer,uint32_t maxSize,uint32_t * contentSize)327 int32_t SerializeTlvWrapper(TlvListNode *head, uint8_t *buffer, uint32_t maxSize, uint32_t *contentSize)
328 {
329 if (head == NULL || buffer == NULL || contentSize == NULL || maxSize == 0) {
330 LOG_ERROR("param is invalid");
331 return PARAM_ERR;
332 }
333 uint32_t offset = 0;
334 TlvListNode *node = head->next;
335 while (node != NULL) {
336 TlvType *tlv = node->data.value;
337 if (tlv == NULL) {
338 LOG_ERROR("tlv is NULL");
339 return PARAM_ERR;
340 }
341 int32_t type = (int32_t)Ntohl(tlv->type);
342 if ((offset > UINT32_MAX - sizeof(int32_t) || offset + sizeof(int32_t) > maxSize) ||
343 (memcpy_s(buffer + offset, sizeof(int32_t), &type, sizeof(int32_t)) != EOK)) {
344 LOG_ERROR("copy type failed");
345 return MEMCPY_ERR;
346 }
347 offset += sizeof(int32_t);
348 uint32_t len = Ntohl(tlv->length);
349 if ((offset > UINT32_MAX - sizeof(int32_t)) || (offset + sizeof(int32_t)) > maxSize ||
350 (memcpy_s(buffer + offset, sizeof(int32_t), &len, sizeof(int32_t)) != EOK)) {
351 LOG_ERROR("copy len failed");
352 return MEMCPY_ERR;
353 }
354 offset += sizeof(int32_t);
355 if ((offset > UINT32_MAX - tlv->length) || (offset + tlv->length > maxSize) ||
356 ((tlv->length != 0) && (memcpy_s(buffer + offset, maxSize - offset, tlv->value, tlv->length) != EOK))) {
357 LOG_ERROR("copy value failed");
358 return MEMCPY_ERR;
359 }
360 offset += tlv->length;
361 node = node->next;
362 }
363
364 *contentSize = offset;
365 return OPERA_SUCC;
366 }