1 /* 2 * Copyright (C) 2025 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 #ifndef CRED_TLV_PARSER_H 17 #define CRED_TLV_PARSER_H 18 19 #include <hc_parcel.h> 20 #include <hc_vector.h> 21 #include <hc_string.h> 22 23 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 #define USE_DEFAULT_TAG 0xFFFF 28 #define CRED_TLV_FAIL (-1) 29 #define NO_REVERT 0 30 #define NEED_REVERT 1 31 #define MAX_TOTOL_LEN (100 * 1024 * 1024) 32 33 typedef struct CredTlvBaseT { 34 unsigned short tag; 35 unsigned int length; 36 unsigned short checkTag; 37 unsigned short hasValue; 38 int64_t (*parse)(struct CredTlvBaseT *, HcParcel *, HcBool); 39 int64_t (*getlen)(struct CredTlvBaseT *); 40 int64_t (*encode)(struct CredTlvBaseT *, HcParcel *); 41 void (*deinit)(struct CredTlvBaseT *); 42 } CredTlvBase; 43 44 #define DECLARE_CRED_TLV_STRUCT(x) \ 45 CredTlvBase base; \ 46 unsigned int offsetCount; \ 47 unsigned int offset[x]; 48 49 unsigned short GetCredTag(unsigned short checkTag, unsigned short defaultTag); 50 51 #define BEGIN_CRED_TLV_STRUCT_DEFINE(TlvS, CheckTag) \ 52 void Init##TlvS(TlvS *tlv, unsigned short checkTag) \ 53 { \ 54 typedef TlvS TlvStructType; \ 55 unsigned int index = 0; \ 56 (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); \ 57 tlv->base.checkTag = GetCredTag(checkTag, CheckTag); 58 59 #define CRED_TLV_MEMBER_OPTION(TlvMember, TlvMemberName, CheckTag) \ 60 Init##TlvMember(&tlv->TlvMemberName, CheckTag); \ 61 tlv->TlvMemberName.base.option = 1; \ 62 tlv->offset[index++] = offsetof(TlvStructType, TlvMemberName); 63 64 #define CRED_TLV_MEMBER(TlvMember, TlvMemberName, CheckTag) \ 65 Init##TlvMember(&tlv->TlvMemberName, CheckTag); \ 66 tlv->offset[index++] = offsetof(TlvStructType, TlvMemberName); 67 68 #define END_CRED_TLV_STRUCT_DEFINE(void) \ 69 tlv->offsetCount = index; \ 70 tlv->base.parse = ParseCredTlvStruct; \ 71 tlv->base.getlen = GetLenCredTlvStruct; \ 72 tlv->base.encode = EncodeCredTlvStruct; \ 73 tlv->base.deinit = DeinitCredTlvStruct; \ 74 } 75 76 #define DECLARE_CRED_TLV_FIX_LENGTH_TYPE(TlvName, TypeName) \ 77 typedef struct \ 78 { \ 79 CredTlvBase base; \ 80 TypeName data; \ 81 } TlvName; 82 83 DECLARE_CRED_TLV_FIX_LENGTH_TYPE(CredTlvInt32, int) 84 DECLARE_CRED_TLV_FIX_LENGTH_TYPE(CredTlvInt16, short) 85 DECLARE_CRED_TLV_FIX_LENGTH_TYPE(CredTlvInt8, char) 86 DECLARE_CRED_TLV_FIX_LENGTH_TYPE(CredTlvUint32, uint32_t) 87 DECLARE_CRED_TLV_FIX_LENGTH_TYPE(CredTlvUint16, uint16_t) 88 DECLARE_CRED_TLV_FIX_LENGTH_TYPE(CredTlvUint8, uint8_t) 89 DECLARE_CRED_TLV_FIX_LENGTH_TYPE(CredTlvUint64, uint64_t) 90 DECLARE_CRED_TLV_FIX_LENGTH_TYPE(CredTlvInt64, uint64_t) 91 92 #define DEFINE_CRED_TLV_FIX_LENGTH_TYPE(TlvName, Revert) \ 93 int64_t ParseCredTlv##TlvName(CredTlvBase *tlv, HcParcel *parcel, HcBool strict) \ 94 { \ 95 (void)strict; \ 96 TlvName *realTlv = (TlvName *)(tlv); \ 97 HcBool readRet = HC_FALSE; \ 98 if (tlv->length != sizeof(realTlv->data)) \ 99 { \ 100 return CRED_TLV_FAIL; \ 101 } \ 102 \ 103 if (Revert) \ 104 { \ 105 readRet = ParcelReadRevert(parcel, &realTlv->data, sizeof(realTlv->data)); \ 106 } else { \ 107 readRet = ParcelRead(parcel, &realTlv->data, sizeof(realTlv->data)); \ 108 } \ 109 if (readRet) \ 110 { \ 111 return tlv->length; \ 112 } else { \ 113 return CRED_TLV_FAIL; \ 114 } \ 115 } \ 116 \ 117 int64_t GetLenCredTlv##TlvName(CredTlvBase *tlv) \ 118 { \ 119 TlvName *realTlv = (TlvName *)(tlv); \ 120 return (int64_t)sizeof(realTlv->data); \ 121 } \ 122 \ 123 int64_t EncodeCredTlv##TlvName(CredTlvBase *tlv, HcParcel *parcel) \ 124 { \ 125 HcBool writeRet = HC_FALSE; \ 126 TlvName *realTlv = (TlvName *)(tlv); \ 127 if (Revert) \ 128 { \ 129 writeRet = ParcelWriteRevert(parcel, &realTlv->data, sizeof(realTlv->data)); \ 130 } else { \ 131 writeRet = ParcelWrite(parcel, &realTlv->data, sizeof(realTlv->data)); \ 132 } \ 133 if (writeRet) \ 134 { \ 135 return sizeof(realTlv->data); \ 136 } else { \ 137 return CRED_TLV_FAIL; \ 138 } \ 139 } \ 140 \ 141 DECLARE_CRED_TLV_PARSE_FUNC(TlvName, ParseCredTlv##TlvName, GetLenCredTlv##TlvName, EncodeCredTlv##TlvName); 142 143 void DeinitCredTlvFixMember(CredTlvBase *tlv); 144 145 #define DECLARE_CRED_TLV_PARSE_FUNC(TlvName, TlvParseFunc, TlvGetLenFunc, TlvEncodeFunc) \ 146 void Init##TlvName(TlvName *tlv, unsigned short checkTag) \ 147 { \ 148 (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); \ 149 tlv->base.parse = TlvParseFunc; \ 150 tlv->base.getlen = TlvGetLenFunc; \ 151 tlv->base.encode = TlvEncodeFunc; \ 152 tlv->base.deinit = DeinitCredTlvFixMember; \ 153 tlv->base.checkTag = checkTag; \ 154 } 155 156 #define CRED_TLV_INIT(TlvName, TlvData) Init##TlvName(TlvData, USE_DEFAULT_TAG); 157 158 #define CRED_TLV_DEINIT(TlvData) TlvData.base.deinit((CredTlvBase *)(&TlvData)); 159 typedef struct { 160 CredTlvBase base; 161 unsigned int offsetCount; 162 unsigned int offset[0]; 163 } CredTlvOffsetExample; 164 165 HcBool ParseCredTlvHead(CredTlvBase *tlv, HcParcel *parcel); 166 int64_t ParseCredTlvNode(CredTlvBase *tlv, HcParcel *parcel, HcBool strict); 167 int64_t GetlenCredTlvNode(CredTlvBase *tlv); 168 void DeinitCredTlvNode(CredTlvBase *tlv); 169 170 int64_t ParseCredTlvStruct(CredTlvBase *tlv, HcParcel *parcel, HcBool strict); 171 int64_t EncodeCredTlvStruct(CredTlvBase *tlv, HcParcel *parcel); 172 int64_t GetLenCredTlvStruct(CredTlvBase *tlv); 173 void DeinitCredTlvStruct(CredTlvBase *tlv); 174 int64_t EncodeCredTlvNode(CredTlvBase *tlv, HcParcel *parcel, HcBool isRoot); 175 HcBool DecodeCredTlvMessage(CredTlvBase *msg, HcParcel *parcel, HcBool strict); 176 HcBool EncodeCredTlvMessage(CredTlvBase *msg, HcParcel *parcel); 177 178 typedef struct { 179 CredTlvBase base; 180 HcParcel data; 181 } CredTlvBuffer; 182 183 void InitCredTlvBuffer(CredTlvBuffer *tlv, unsigned short checkTag); 184 int64_t ParseCredTlvBuffer(CredTlvBase *tlv, HcParcel *parcel, HcBool strict); 185 int64_t GetlenCredTlvBuffer(CredTlvBase *tlv); 186 int64_t EncodeCredTlvBuffer(CredTlvBase *tlv, HcParcel *parcel); 187 void DeinitCredTlvBuffer(CredTlvBase *tlv); 188 189 typedef struct { 190 CredTlvBase base; 191 HcString data; 192 } CredTlvString; 193 194 void InitCredTlvString(CredTlvString *tlv, unsigned short checkTag); 195 int64_t ParseCredTlvString(CredTlvBase *tlv, HcParcel *parcel, HcBool strict); 196 int64_t GetlenCredTlvString(CredTlvBase *tlv); 197 int64_t EncodeCredTlvString(CredTlvBase *tlv, HcParcel *parcel); 198 void DeinitCredTlvString(CredTlvBase *tlv); 199 200 #define DECLEAR_CRED_INIT_FUNC(TlvStruct) \ 201 void Init##TlvStruct(TlvStruct *tlv, unsigned short checkTag); 202 203 DECLEAR_CRED_INIT_FUNC(CredTlvUint64) 204 DECLEAR_CRED_INIT_FUNC(CredTlvUint32) 205 DECLEAR_CRED_INIT_FUNC(CredTlvUint16) 206 DECLEAR_CRED_INIT_FUNC(CredTlvUint8) 207 DECLEAR_CRED_INIT_FUNC(CredTlvInt64) 208 DECLEAR_CRED_INIT_FUNC(CredTlvInt32) 209 DECLEAR_CRED_INIT_FUNC(CredTlvInt16) 210 DECLEAR_CRED_INIT_FUNC(CredTlvInt8) 211 212 #define DECLARE_CRED_TLV_VECTOR(TlvVecName, TlvVecElement) \ 213 DECLARE_HC_VECTOR(Vec##TlvVecName, TlvVecElement) \ 214 typedef struct { \ 215 CredTlvBase base; \ 216 Vec##TlvVecName data; \ 217 } TlvVecName; \ 218 void DeinitTlv##TlvVecName(CredTlvBase *tlv); \ 219 void Init##TlvVecName(TlvVecName *tlv, unsigned short checkTag); 220 221 #define IMPLEMENT_CRED_TLV_VECTOR(TlvVecName, TlvElementName, VecAllocCount) \ 222 IMPLEMENT_HC_VECTOR(Vec##TlvVecName, TlvElementName, VecAllocCount) \ 223 int64_t ParseTlv##TlvVecName(CredTlvBase *tlv, HcParcel *parcel, HcBool strict) \ 224 { \ 225 TlvVecName *realTlv = (TlvVecName *)(tlv); \ 226 uint32_t count = 0; \ 227 if (!ParcelReadUint32(parcel, &count)) { \ 228 return CRED_TLV_FAIL; \ 229 } \ 230 int64_t totalLen = sizeof(count); \ 231 uint32_t index = 0; \ 232 for (index = 0; index < count; ++index) { \ 233 TlvElementName tlvElement; \ 234 TlvElementName *curElement = realTlv->data.pushBack(&realTlv->data, &tlvElement); \ 235 if (curElement == NULL) { \ 236 return CRED_TLV_FAIL; \ 237 } \ 238 CRED_TLV_INIT(TlvElementName, curElement); \ 239 \ 240 int64_t elementLen = ParseCredTlvNode((CredTlvBase *)curElement, parcel, strict); \ 241 if (elementLen < 0) { \ 242 return CRED_TLV_FAIL; \ 243 } \ 244 totalLen += elementLen; \ 245 if (totalLen >= MAX_TOTOL_LEN) { \ 246 return CRED_TLV_FAIL; \ 247 } \ 248 } \ 249 \ 250 return totalLen; \ 251 } \ 252 \ 253 int64_t EncodeTlv##TlvVecName(CredTlvBase *tlv, HcParcel *parcel) \ 254 { \ 255 TlvVecName *realTlv = (TlvVecName *)(tlv); \ 256 uint32_t index = 0; \ 257 TlvElementName *element = NULL; \ 258 int64_t totalLen = 4; \ 259 uint32_t count = realTlv->data.size(&realTlv->data); \ 260 if (!ParcelWriteUint32(parcel, count)) { \ 261 return CRED_TLV_FAIL; \ 262 } \ 263 \ 264 FOR_EACH_HC_VECTOR(realTlv->data, index, element) { \ 265 if (element != NULL) { \ 266 int64_t len = EncodeCredTlvNode((CredTlvBase *)element, parcel, HC_FALSE); \ 267 totalLen += len; \ 268 if (totalLen >= MAX_TOTOL_LEN) { \ 269 return CRED_TLV_FAIL; \ 270 } \ 271 } \ 272 } \ 273 return totalLen; \ 274 } \ 275 int64_t GetLenTlv##TlvVecName(CredTlvBase *tlv) \ 276 { \ 277 TlvVecName *realTlv = (TlvVecName *)(tlv); \ 278 uint32_t index = 0; \ 279 TlvElementName *element = NULL; \ 280 int64_t totalLen = sizeof(int32_t); \ 281 FOR_EACH_HC_VECTOR(realTlv->data, index, element) { \ 282 if (element != NULL) { \ 283 totalLen += GetlenCredTlvNode((CredTlvBase *)element); \ 284 if (totalLen >= MAX_TOTOL_LEN) { \ 285 return CRED_TLV_FAIL; \ 286 } \ 287 } else { \ 288 return CRED_TLV_FAIL; \ 289 } \ 290 } \ 291 return totalLen; \ 292 } \ 293 \ 294 void DeinitTlv##TlvVecName(CredTlvBase *tlv) \ 295 { \ 296 TlvVecName *realTlv = (TlvVecName *)(tlv); \ 297 uint32_t index = 0; \ 298 TlvElementName *element = NULL; \ 299 FOR_EACH_HC_VECTOR(realTlv->data, index, element) { \ 300 if (element != NULL) { \ 301 CRED_TLV_DEINIT((*element)); \ 302 } \ 303 } \ 304 DESTROY_HC_VECTOR(Vec##TlvVecName, &((TlvVecName *)tlv)->data); \ 305 } \ 306 \ 307 void Init##TlvVecName(TlvVecName *tlv, unsigned short checkTag) \ 308 { \ 309 (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base)); \ 310 tlv->base.parse = ParseTlv##TlvVecName; \ 311 tlv->base.encode = EncodeTlv##TlvVecName; \ 312 tlv->base.getlen = GetLenTlv##TlvVecName; \ 313 tlv->base.deinit = DeinitTlv##TlvVecName; \ 314 tlv->base.checkTag = checkTag; \ 315 tlv->data = CREATE_HC_VECTOR(Vec##TlvVecName); \ 316 } 317 318 #ifdef __cplusplus 319 } 320 #endif 321 #endif 322