• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "utils_tlv.h"
17 
18 #include <securec.h>
19 
20 #define TLV_TAG_LEN sizeof(uint16_t)
21 #define TLV_LENGTH_LEN sizeof(uint16_t)
22 #define TLV_TLV_HEAD_LEN (TLV_TAG_LEN + TLV_LENGTH_LEN)
23 
GetNextTlv(const uint8_t * buffer)24 static uint8_t *GetNextTlv(const uint8_t *buffer)
25 {
26     return (uint8_t *)buffer + ((TlvCommon *)buffer)->len + TLV_TLV_HEAD_LEN;
27 }
28 
ParseTlv(const uint8_t * buffer,TlvCommon * tlv,const uint8_t * boundary,uint32_t * retCode)29 static uint8_t *ParseTlv(const uint8_t *buffer, TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
30 {
31     if (buffer + TLV_TLV_HEAD_LEN > boundary) {
32         *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
33         return NULL;
34     }
35     if (GetNextTlv(buffer) > boundary) {
36         *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
37         return NULL;
38     }
39     tlv->tag = ((TlvCommon *)buffer)->tag;
40     tlv->len = ((TlvCommon *)buffer)->len;
41     tlv->value = (uint8_t *)buffer + TLV_TLV_HEAD_LEN;
42     *retCode = TLV_OK;
43     return GetNextTlv(buffer);
44 }
45 
AppendTlv(uint8_t * buffer,const TlvCommon * tlv,const uint8_t * boundary,uint32_t * retCode)46 static uint8_t *AppendTlv(uint8_t *buffer, const TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
47 {
48     if (buffer > boundary) {
49         *retCode = TLV_ERR_BUFF_NO_ENOUGH;
50         return NULL;
51     }
52     if (buffer + ((TlvCommon *)tlv)->len + TLV_TLV_HEAD_LEN > boundary) {
53         *retCode = TLV_ERR_BUFF_NO_ENOUGH;
54         return NULL;
55     }
56     ((TlvCommon *)buffer)->tag = tlv->tag;
57     ((TlvCommon *)buffer)->len = tlv->len;
58     if (tlv->len != 0 && tlv->value != NULL) {
59         if (memcpy_s(buffer + TLV_TLV_HEAD_LEN, boundary - buffer - TLV_TLV_HEAD_LEN, tlv->value, tlv->len) != EOK) {
60             *retCode = TLV_ERR_BUFF_NO_ENOUGH;
61             return NULL;
62         }
63     }
64     *retCode = TLV_OK;
65     return GetNextTlv(buffer);
66 }
67 
Serialize(const TlvCommon * tlv,uint32_t tlvCount,uint8_t * buff,uint32_t maxBuffSize,uint32_t * buffSize)68 uint32_t Serialize(const TlvCommon *tlv, uint32_t tlvCount, uint8_t *buff, uint32_t maxBuffSize, uint32_t *buffSize)
69 {
70     if (tlv == NULL || buff == NULL || buffSize == NULL) {
71         return TLV_ERR_INVALID_PARA;
72     }
73 
74     uint8_t *curr = buff;
75     uint8_t *boundary = buff + maxBuffSize;
76 
77     uint32_t retCode = TLV_OK;
78     for (uint32_t index = 0; index < tlvCount; index++) {
79         curr = AppendTlv(curr, &tlv[index], boundary, &retCode);
80         if (curr == NULL || retCode != TLV_OK) {
81             return retCode;
82         }
83     }
84     *buffSize = curr - buff;
85     return TLV_OK;
86 }
87 
Deserialize(const uint8_t * buff,uint32_t buffSize,TlvCommon * tlv,uint32_t maxTlvCount,uint32_t * tlvCount)88 uint32_t Deserialize(const uint8_t *buff, uint32_t buffSize, TlvCommon *tlv, uint32_t maxTlvCount, uint32_t *tlvCount)
89 {
90     if (buff == NULL || tlv == NULL || tlvCount == NULL) {
91         return TLV_ERR_INVALID_PARA;
92     }
93 
94     uint8_t *msg = (uint8_t *)buff;
95     const uint8_t *boundary = buff + buffSize;
96     uint32_t index = 0;
97 
98     while (msg != NULL) {
99         if (index >= maxTlvCount) {
100             return TLV_ERR_BUFF_NO_ENOUGH;
101         }
102         uint32_t retCode = TLV_OK;
103         msg = ParseTlv(msg, &tlv[index], boundary, &retCode);
104         if (msg == NULL || retCode != TLV_OK) {
105             break;
106         }
107         index++;
108     }
109 
110     *tlvCount = index;
111     return TLV_OK;
112 }
113