12ee81decSopenharmony_ci/*
22ee81decSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
32ee81decSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42ee81decSopenharmony_ci * you may not use this file except in compliance with the License.
52ee81decSopenharmony_ci * You may obtain a copy of the License at
62ee81decSopenharmony_ci *
72ee81decSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
82ee81decSopenharmony_ci *
92ee81decSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102ee81decSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112ee81decSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122ee81decSopenharmony_ci * See the License for the specific language governing permissions and
132ee81decSopenharmony_ci * limitations under the License.
142ee81decSopenharmony_ci */
152ee81decSopenharmony_ci
162ee81decSopenharmony_ci#include "utils_tlv.h"
172ee81decSopenharmony_ci
182ee81decSopenharmony_ci#include <stddef.h>
192ee81decSopenharmony_ci
202ee81decSopenharmony_ci#include "securec.h"
212ee81decSopenharmony_ci
222ee81decSopenharmony_ci#define TLV_TAG_LEN sizeof(uint16_t)
232ee81decSopenharmony_ci#define TLV_LENGTH_LEN sizeof(uint16_t)
242ee81decSopenharmony_ci#define TLV_TLV_HEAD_LEN (TLV_TAG_LEN + TLV_LENGTH_LEN)
252ee81decSopenharmony_ci
262ee81decSopenharmony_cistatic uint8_t *GetNextTlv(const uint8_t *buffer)
272ee81decSopenharmony_ci{
282ee81decSopenharmony_ci    return (uint8_t *)buffer + ((TlvCommon *)buffer)->len + TLV_TLV_HEAD_LEN;
292ee81decSopenharmony_ci}
302ee81decSopenharmony_ci
312ee81decSopenharmony_cistatic uint8_t *ParseTlv(const uint8_t *buffer, TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
322ee81decSopenharmony_ci{
332ee81decSopenharmony_ci    if (buffer + TLV_TLV_HEAD_LEN > boundary) {
342ee81decSopenharmony_ci        *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
352ee81decSopenharmony_ci        return NULL;
362ee81decSopenharmony_ci    }
372ee81decSopenharmony_ci    if (GetNextTlv(buffer) > boundary) {
382ee81decSopenharmony_ci        *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
392ee81decSopenharmony_ci        return NULL;
402ee81decSopenharmony_ci    }
412ee81decSopenharmony_ci    tlv->tag = ((TlvCommon *)buffer)->tag;
422ee81decSopenharmony_ci    tlv->len = ((TlvCommon *)buffer)->len;
432ee81decSopenharmony_ci    tlv->value = (uint8_t *)buffer + TLV_TLV_HEAD_LEN;
442ee81decSopenharmony_ci    *retCode = TLV_OK;
452ee81decSopenharmony_ci    return GetNextTlv(buffer);
462ee81decSopenharmony_ci}
472ee81decSopenharmony_ci
482ee81decSopenharmony_cistatic uint8_t *AppendTlv(uint8_t *buffer, const TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
492ee81decSopenharmony_ci{
502ee81decSopenharmony_ci    if (buffer > boundary) {
512ee81decSopenharmony_ci        *retCode = TLV_ERR_BUFF_NO_ENOUGH;
522ee81decSopenharmony_ci        return NULL;
532ee81decSopenharmony_ci    }
542ee81decSopenharmony_ci    if (buffer + ((TlvCommon *)tlv)->len + TLV_TLV_HEAD_LEN > boundary) {
552ee81decSopenharmony_ci        *retCode = TLV_ERR_BUFF_NO_ENOUGH;
562ee81decSopenharmony_ci        return NULL;
572ee81decSopenharmony_ci    }
582ee81decSopenharmony_ci    ((TlvCommon *)buffer)->tag = tlv->tag;
592ee81decSopenharmony_ci    ((TlvCommon *)buffer)->len = tlv->len;
602ee81decSopenharmony_ci    if (tlv->len != 0 && tlv->value != NULL) {
612ee81decSopenharmony_ci        if (memcpy_s(buffer + TLV_TLV_HEAD_LEN, boundary - buffer - TLV_TLV_HEAD_LEN, tlv->value, tlv->len) != EOK) {
622ee81decSopenharmony_ci            *retCode = TLV_ERR_BUFF_NO_ENOUGH;
632ee81decSopenharmony_ci            return NULL;
642ee81decSopenharmony_ci        }
652ee81decSopenharmony_ci    }
662ee81decSopenharmony_ci    *retCode = TLV_OK;
672ee81decSopenharmony_ci    return GetNextTlv(buffer);
682ee81decSopenharmony_ci}
692ee81decSopenharmony_ci
702ee81decSopenharmony_ciuint32_t Serialize(const TlvCommon *tlv, uint32_t tlvCount, uint8_t *buff, uint32_t maxBuffSize, uint32_t *buffSize)
712ee81decSopenharmony_ci{
722ee81decSopenharmony_ci    if (tlv == NULL || buff == NULL || buffSize == NULL) {
732ee81decSopenharmony_ci        return TLV_ERR_INVALID_PARA;
742ee81decSopenharmony_ci    }
752ee81decSopenharmony_ci
762ee81decSopenharmony_ci    uint8_t *curr = buff;
772ee81decSopenharmony_ci    uint8_t *boundary = buff + maxBuffSize;
782ee81decSopenharmony_ci
792ee81decSopenharmony_ci    uint32_t retCode = TLV_OK;
802ee81decSopenharmony_ci    for (uint32_t index = 0; index < tlvCount; index++) {
812ee81decSopenharmony_ci        curr = AppendTlv(curr, &tlv[index], boundary, &retCode);
822ee81decSopenharmony_ci        if (curr == NULL || retCode != TLV_OK) {
832ee81decSopenharmony_ci            return retCode;
842ee81decSopenharmony_ci        }
852ee81decSopenharmony_ci    }
862ee81decSopenharmony_ci    *buffSize = curr - buff;
872ee81decSopenharmony_ci    return TLV_OK;
882ee81decSopenharmony_ci}
892ee81decSopenharmony_ci
902ee81decSopenharmony_ciuint32_t Deserialize(const uint8_t *buff, uint32_t buffSize, TlvCommon *tlv, uint32_t maxTlvCount, uint32_t *tlvCount)
912ee81decSopenharmony_ci{
922ee81decSopenharmony_ci    if (buff == NULL || tlv == NULL || tlvCount == NULL) {
932ee81decSopenharmony_ci        return TLV_ERR_INVALID_PARA;
942ee81decSopenharmony_ci    }
952ee81decSopenharmony_ci
962ee81decSopenharmony_ci    uint8_t *msg = (uint8_t *)buff;
972ee81decSopenharmony_ci    const uint8_t *boundary = buff + buffSize;
982ee81decSopenharmony_ci    uint32_t index = 0;
992ee81decSopenharmony_ci
1002ee81decSopenharmony_ci    while (msg != NULL) {
1012ee81decSopenharmony_ci        if (index >= maxTlvCount) {
1022ee81decSopenharmony_ci            return TLV_ERR_BUFF_NO_ENOUGH;
1032ee81decSopenharmony_ci        }
1042ee81decSopenharmony_ci        uint32_t retCode = TLV_OK;
1052ee81decSopenharmony_ci        msg = ParseTlv(msg, &tlv[index], boundary, &retCode);
1062ee81decSopenharmony_ci        if (msg == NULL || retCode != TLV_OK) {
1072ee81decSopenharmony_ci            break;
1082ee81decSopenharmony_ci        }
1092ee81decSopenharmony_ci        index++;
1102ee81decSopenharmony_ci    }
1112ee81decSopenharmony_ci
1122ee81decSopenharmony_ci    *tlvCount = index;
1132ee81decSopenharmony_ci    return TLV_OK;
1142ee81decSopenharmony_ci}
115