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 (48 * 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