1 /*
2 * Copyright (C) 2021 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 "hc_tlv_parser.h"
17 #include <stddef.h>
18
19 #define MAX_TLV_LENGTH (32 * 1024)
20
ParseTlvHead(TlvBase * tlv,HcParcel * parcel)21 HcBool ParseTlvHead(TlvBase *tlv, HcParcel *parcel)
22 {
23 #ifdef IS_BIG_ENDIAN
24 if (!ParcelReadUint16Revert(parcel, &tlv->tag)) {
25 return HC_FALSE;
26 }
27 #else
28 if (!ParcelReadUint16(parcel, &tlv->tag)) {
29 return HC_FALSE;
30 }
31 #endif
32
33 if (tlv->tag != tlv->checkTag) {
34 return HC_FALSE;
35 }
36 #ifdef IS_BIG_ENDIAN
37 if (!ParcelReadUint16Revert(parcel, &tlv->length)) {
38 return HC_FALSE;
39 }
40 #else
41 if (!ParcelReadUint16(parcel, &tlv->length)) {
42 return HC_FALSE;
43 }
44 #endif
45 if (tlv->length > MAX_TLV_LENGTH) {
46 return HC_FALSE;
47 }
48 return HC_TRUE;
49 }
50
ParseTlvNode(TlvBase * tlv,HcParcel * parcel,HcBool strict)51 int32_t ParseTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool strict)
52 {
53 if (!ParseTlvHead(tlv, parcel)) {
54 return TLV_FAIL;
55 } else {
56 if (GetParcelDataSize(parcel) < tlv->length) {
57 return TLV_FAIL;
58 }
59
60 int ret = tlv->parse(tlv, parcel, strict);
61 if (ret < 0 || ret > MAX_TLV_LENGTH) {
62 return TLV_FAIL;
63 } else {
64 return ret + sizeof(tlv->tag) + sizeof(tlv->length);
65 }
66 }
67 }
68
GetlenTlvNode(TlvBase * tlv)69 int32_t GetlenTlvNode(TlvBase *tlv)
70 {
71 int32_t bodyLen = tlv->getlen(tlv);
72 if (bodyLen < 0 || bodyLen > MAX_TLV_LENGTH) {
73 return TLV_FAIL;
74 } else {
75 tlv->length = bodyLen + sizeof(tlv->tag) + sizeof(tlv->length);
76 return tlv->length;
77 }
78 }
79
DeinitTlvNode(TlvBase * tlv)80 void DeinitTlvNode(TlvBase *tlv)
81 {
82 if (tlv != NULL) {
83 tlv->deinit(tlv);
84 }
85 }
86
EncodeTlvNode(TlvBase * tlv,HcParcel * parcel,HcBool isRoot)87 int32_t EncodeTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool isRoot)
88 {
89 int32_t bodyLen = tlv->getlen(tlv);
90 if (bodyLen < 0 || bodyLen > MAX_TLV_LENGTH) {
91 return TLV_FAIL;
92 } else if (bodyLen == 0) {
93 if (isRoot) {
94 ResetParcel(parcel, sizeof(uint16_t) + sizeof(uint16_t), 0);
95 }
96 #ifdef IS_BIG_ENDIAN
97 ParcelWriteUint16Revert(parcel, tlv->checkTag);
98 ParcelWriteUint16Revert(parcel, bodyLen);
99 #else
100 ParcelWriteUint16(parcel, tlv->checkTag);
101 ParcelWriteUint16(parcel, bodyLen);
102 #endif
103 return sizeof(tlv->tag) + sizeof(tlv->length);
104 } else { // has value
105 if (isRoot) {
106 ResetParcel(parcel, sizeof(uint16_t) + sizeof(uint16_t) + bodyLen, 0);
107 }
108 int32_t encodeLen;
109 tlv->length = (uint16_t)bodyLen;
110 #ifdef IS_BIG_ENDIAN
111 ParcelWriteUint16Revert(parcel, tlv->checkTag);
112 ParcelWriteUint16Revert(parcel, tlv->length);
113 #else
114 ParcelWriteUint16(parcel, tlv->checkTag);
115 ParcelWriteUint16(parcel, tlv->length);
116 #endif
117 encodeLen = tlv->encode(tlv, parcel);
118 if (encodeLen < 0 || encodeLen > MAX_TLV_LENGTH) {
119 return TLV_FAIL;
120 } else {
121 return encodeLen + sizeof(tlv->tag) + sizeof(tlv->length);
122 }
123 }
124 }
125
GetEmptyStructNode(TlvBase * tlv,unsigned short tag)126 TlvBase* GetEmptyStructNode(TlvBase *tlv, unsigned short tag)
127 {
128 if (tlv == NULL) {
129 return NULL;
130 }
131
132 unsigned int index;
133 unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
134 unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
135 for (index = 0; index < memberCount; ++index) {
136 TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
137 if (tlvChild->checkTag == tag && tlvChild->hasValue == 0) {
138 return tlvChild;
139 }
140 }
141
142 return NULL;
143 }
144
CheckStructNodeAllHasValue(TlvBase * tlv)145 int32_t CheckStructNodeAllHasValue(TlvBase *tlv)
146 {
147 if (tlv == NULL) {
148 return 0;
149 } else {
150 unsigned int index;
151 unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
152 unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
153 for (index = 0; index < memberCount; ++index) {
154 TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
155 if (tlvChild->hasValue == 0) {
156 return -1;
157 }
158 }
159 }
160
161 return 0;
162 }
163
SetStructNodeHasValue(TlvBase * tlv)164 void SetStructNodeHasValue(TlvBase *tlv)
165 {
166 if (tlv != NULL) {
167 tlv->hasValue = 1;
168 }
169 }
170
ParseAndSkipTlvUnknownNode(HcParcel * parcel)171 int32_t ParseAndSkipTlvUnknownNode(HcParcel *parcel)
172 {
173 // read tag
174 uint16_t tag = 0;
175 if (!ParcelReadUint16(parcel, &tag)) {
176 return TLV_FAIL;
177 }
178
179 // read length
180 uint16_t length = 0;
181 if (!ParcelReadUint16(parcel, &length)) {
182 return TLV_FAIL;
183 }
184
185 // pop data
186 if (!ParcelPopFront(parcel, length)) {
187 return TLV_FAIL;
188 }
189
190 return sizeof(tag) + sizeof(length) + length;
191 }
192
ParseTlvStruct(TlvBase * tlv,HcParcel * parcel,HcBool strict)193 int32_t ParseTlvStruct(TlvBase *tlv, HcParcel *parcel, HcBool strict)
194 {
195 uint32_t childTotalLength = 0;
196 do {
197 uint16_t tag = 0;
198 if (!ParcelReadWithoutPopData(parcel, &tag, sizeof(tag))) {
199 return TLV_FAIL;
200 }
201 TlvBase *tlvChild = GetEmptyStructNode(tlv, tag);
202 if (tlvChild == NULL) {
203 if (strict) {
204 return TLV_FAIL;
205 }
206
207 int32_t unknownChildLength = ParseAndSkipTlvUnknownNode(parcel);
208 if (unknownChildLength < 0 || unknownChildLength > MAX_TLV_LENGTH) {
209 return TLV_FAIL;
210 }
211 childTotalLength += unknownChildLength;
212 if (childTotalLength > MAX_TLV_LENGTH) {
213 return TLV_FAIL;
214 }
215 } else {
216 int32_t childLength = ParseTlvNode(tlvChild, parcel, strict);
217 if (childLength < 0 || childLength > MAX_TLV_LENGTH) {
218 return TLV_FAIL;
219 }
220 SetStructNodeHasValue(tlvChild);
221 childTotalLength += childLength;
222 if (childTotalLength > MAX_TLV_LENGTH) {
223 return TLV_FAIL;
224 }
225 }
226 } while (childTotalLength < tlv->length);
227
228 if (childTotalLength > tlv->length) {
229 return TLV_FAIL;
230 }
231
232 if (strict && CheckStructNodeAllHasValue(tlv) != 0) {
233 return TLV_FAIL;
234 }
235
236 return childTotalLength;
237 }
238
EncodeTlvStruct(TlvBase * tlv,HcParcel * parcel)239 int32_t EncodeTlvStruct(TlvBase *tlv, HcParcel *parcel)
240 {
241 unsigned int index;
242 unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
243 unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
244
245 uint32_t totalLen = 0;
246 for (index = 0; index < memberCount; ++index) {
247 TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
248 int32_t childLen = EncodeTlvNode(tlvChild, parcel, HC_FALSE);
249 if (childLen < 0 || childLen > MAX_TLV_LENGTH) {
250 return TLV_FAIL;
251 } else {
252 totalLen += childLen;
253 }
254 if (totalLen > MAX_TLV_LENGTH) {
255 return TLV_FAIL;
256 }
257 }
258
259 return totalLen;
260 }
261
GetLenTlvStruct(TlvBase * tlv)262 int32_t GetLenTlvStruct(TlvBase *tlv)
263 {
264 unsigned int index;
265 unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
266 unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
267 uint32_t childTotalLength = 0;
268
269 for (index = 0; index < memberCount; ++index) {
270 TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
271 int32_t childLength = GetlenTlvNode(tlvChild);
272 if (childLength <= 0 || childLength > MAX_TLV_LENGTH) {
273 return TLV_FAIL;
274 } else {
275 childTotalLength += childLength;
276 }
277 if (childTotalLength > MAX_TLV_LENGTH) {
278 return TLV_FAIL;
279 }
280 }
281
282 return childTotalLength;
283 }
284
DeinitTlvStruct(TlvBase * tlv)285 void DeinitTlvStruct(TlvBase *tlv)
286 {
287 unsigned int index;
288 unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
289 unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
290
291 for (index = 0; index < memberCount; ++index) {
292 TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
293 DeinitTlvNode(tlvChild);
294 }
295 }
296
DecodeTlvMessage(TlvBase * msg,HcParcel * parcel,HcBool strict)297 HcBool DecodeTlvMessage(TlvBase *msg, HcParcel *parcel, HcBool strict)
298 {
299 if (msg == NULL || parcel == NULL) {
300 return HC_FALSE;
301 } else {
302 int32_t msgLen = ParseTlvNode(msg, parcel, strict);
303 if (msgLen > MAX_TLV_LENGTH) {
304 return HC_FALSE;
305 }
306 if ((int32_t)(msg->length + sizeof(msg->length) + sizeof(msg->tag)) != msgLen) {
307 return HC_FALSE;
308 }
309
310 if (GetParcelDataSize(parcel) != 0) {
311 return HC_FALSE;
312 }
313 }
314
315 return HC_TRUE;
316 }
317
318
EncodeTlvMessage(TlvBase * msg,HcParcel * parcel)319 HcBool EncodeTlvMessage(TlvBase *msg, HcParcel *parcel)
320 {
321 if (msg == NULL || parcel == NULL) {
322 return HC_FALSE;
323 } else {
324 if (EncodeTlvNode(msg, parcel, HC_TRUE) < 0) {
325 return HC_FALSE;
326 }
327 }
328
329 return HC_TRUE;
330 }
331
ParseTlvBuffer(TlvBase * tlv,HcParcel * parcel,HcBool strict)332 int32_t ParseTlvBuffer(TlvBase *tlv, HcParcel *parcel, HcBool strict)
333 {
334 (void)strict;
335 TlvBuffer *realTlv = (TlvBuffer *)(tlv);
336 if (tlv->length == 0 || ParcelReadParcel(parcel, &realTlv->data, tlv->length, HC_FALSE)) {
337 return tlv->length;
338 } else {
339 return TLV_FAIL;
340 }
341 }
342
GetlenTlvBuffer(TlvBase * tlv)343 int32_t GetlenTlvBuffer(TlvBase *tlv)
344 {
345 TlvBuffer *realTlv = (TlvBuffer *)(tlv);
346 return (int32_t)GetParcelDataSize(&realTlv->data);
347 }
348
EncodeTlvBuffer(TlvBase * tlv,HcParcel * parcel)349 int32_t EncodeTlvBuffer(TlvBase *tlv, HcParcel *parcel)
350 {
351 TlvBuffer *realTlv = (TlvBuffer *)(tlv);
352 int32_t len = GetlenTlvBuffer(tlv);
353 if (len <= 0 || len > MAX_TLV_LENGTH) {
354 return TLV_FAIL;
355 }
356
357 if (ParcelReadParcel(&realTlv->data, parcel, len, HC_TRUE)) {
358 return len;
359 } else {
360 return TLV_FAIL;
361 }
362 }
363
DeinitTlvBuffer(TlvBase * tlv)364 void DeinitTlvBuffer(TlvBase *tlv)
365 {
366 DeleteParcel(&((TlvBuffer *)tlv)->data);
367 }
368
InitTlvBuffer(TlvBuffer * tlv,unsigned short checkTag)369 void InitTlvBuffer(TlvBuffer *tlv, unsigned short checkTag)
370 {
371 (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base));
372 tlv->base.parse = ParseTlvBuffer;
373 tlv->base.getlen = GetlenTlvBuffer;
374 tlv->base.encode = EncodeTlvBuffer;
375 tlv->base.deinit = DeinitTlvBuffer;
376 tlv->base.checkTag = checkTag;
377 tlv->data = CreateParcel(PARCEL_DEFAULT_LENGTH, PARCEL_DEFAULT_ALLOC_UNIT);
378 }
379
ParseTlvString(TlvBase * tlv,HcParcel * parcel,HcBool strict)380 int32_t ParseTlvString(TlvBase *tlv, HcParcel *parcel, HcBool strict)
381 {
382 (void)strict;
383 TlvString *realTlv = (TlvString *)(tlv);
384 ClearParcel(&realTlv->data.parcel);
385 if (tlv->length == 0 || ParcelReadParcel(parcel, &realTlv->data.parcel, tlv->length, HC_FALSE)) {
386 return tlv->length;
387 } else {
388 return TLV_FAIL;
389 }
390 }
391
GetlenTlvString(TlvBase * tlv)392 int32_t GetlenTlvString(TlvBase *tlv)
393 {
394 TlvString *realTlv = (TlvString *)(tlv);
395 return (int32_t)GetParcelDataSize(&realTlv->data.parcel);
396 }
397
EncodeTlvString(TlvBase * tlv,HcParcel * parcel)398 int32_t EncodeTlvString(TlvBase *tlv, HcParcel *parcel)
399 {
400 TlvString *realTlv = (TlvString *)(tlv);
401 int32_t len = GetlenTlvString(tlv);
402 if (len <= 0 || len > MAX_TLV_LENGTH) {
403 return TLV_FAIL;
404 }
405
406 if (ParcelReadParcel(&realTlv->data.parcel, parcel, len, HC_TRUE)) {
407 return len;
408 } else {
409 return TLV_FAIL;
410 }
411 }
412
DeinitTlvString(TlvBase * tlv)413 void DeinitTlvString(TlvBase *tlv)
414 {
415 DeleteString(&((TlvString*)tlv)->data);
416 }
417
InitTlvString(TlvString * tlv,unsigned short checkTag)418 void InitTlvString(TlvString *tlv, unsigned short checkTag)
419 {
420 (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base));
421 tlv->base.parse = ParseTlvString;
422 tlv->base.getlen = GetlenTlvString;
423 tlv->base.encode = EncodeTlvString;
424 tlv->base.deinit = DeinitTlvString;
425 tlv->base.checkTag = checkTag;
426 tlv->data = CreateString();
427 }
428
GetTag(unsigned short checkTag,unsigned short defaultTag)429 unsigned short GetTag(unsigned short checkTag, unsigned short defaultTag)
430 {
431 if (checkTag == USE_DEFAULT_TAG) {
432 return defaultTag;
433 } else {
434 return checkTag;
435 }
436 }
437
DeinitTlvFixMember(TlvBase * tlv)438 void DeinitTlvFixMember(TlvBase* tlv)
439 {
440 (void)tlv;
441 return;
442 }
443
444 #ifdef IS_BIG_ENDIAN
445 DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt64, NEED_REVERT)
446 DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt32, NEED_REVERT)
447 DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt16, NEED_REVERT)
448 DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt8, NEED_REVERT)
449 DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint64, NEED_REVERT)
450 DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint32, NEED_REVERT)
451 DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint16, NEED_REVERT)
452 DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint8, NEED_REVERT)
453 #else
454 DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt64, NO_REVERT)
455 DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt32, NO_REVERT)
456 DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt16, NO_REVERT)
457 DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt8, NO_REVERT)
458 DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint64, NO_REVERT)
459 DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint32, NO_REVERT)
460 DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint16, NO_REVERT)
461 DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint8, NO_REVERT)
462 #endif
463