• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }