1 /*
2  * Copyright (c) 2024 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 "tlv_utils.h"
17 
18 #include "securec.h"
19 #include "netstack_log.h"
20 
21 namespace OHOS::NetStack {
22 
23 #define DFX_MSG_FIELD_NUM 30
24 #define BUFFER_MAX_SIZE (1 * 256 * 1024)
25 
26 #define TLV_TAG_LEN sizeof(uint32_t)
27 #define TLV_LENGTH_LEN sizeof(uint32_t)
28 #define TLV_TLV_HEAD_LEN (TLV_TAG_LEN + TLV_LENGTH_LEN)
29 
GetNextTlv(const uint8_t * buffer)30 uint8_t *TlvUtils::GetNextTlv(const uint8_t *buffer)
31 {
32     return const_cast<uint8_t *>(buffer) + (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->len_ +
33            TLV_TLV_HEAD_LEN;
34 }
35 
ParseTlv(const uint8_t * buffer,TlvCommon * tlv,const uint8_t * boundary,uint32_t * retCode)36 uint8_t *TlvUtils::ParseTlv(const uint8_t *buffer, TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
37 {
38     if (buffer + TLV_TLV_HEAD_LEN > boundary) {
39         *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
40         return nullptr;
41     }
42     if (GetNextTlv(buffer) > boundary) {
43         *retCode = TLV_ERR_PARSE_PAYLOAD_ERR;
44         return nullptr;
45     }
46     tlv->tag_ = (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->tag_;
47     tlv->len_ = (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->len_;
48     tlv->value_ = const_cast<uint8_t *>(buffer) + TLV_TLV_HEAD_LEN;
49     *retCode = TLV_OK;
50     return GetNextTlv(buffer);
51 }
52 
AppendTlv(uint8_t * buffer,const TlvCommon * tlv,const uint8_t * boundary,uint32_t * retCode)53 uint8_t *TlvUtils::AppendTlv(uint8_t *buffer, const TlvCommon *tlv, const uint8_t *boundary, uint32_t *retCode)
54 {
55     if (buffer > boundary) {
56         *retCode = TLV_ERR_BUFF_NO_ENOUGH;
57         return nullptr;
58     }
59     if (buffer + (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->len_ + TLV_TLV_HEAD_LEN > boundary) {
60         *retCode = TLV_ERR_BUFF_NO_ENOUGH;
61         return nullptr;
62     }
63     (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->tag_ = tlv->tag_;
64     (reinterpret_cast<TlvCommon *>(const_cast<uint8_t *>(buffer)))->len_ = tlv->len_;
65     if (tlv->len_ != 0 && tlv->value_ != nullptr) {
66         if (memcpy_s(buffer + TLV_TLV_HEAD_LEN, boundary - buffer - TLV_TLV_HEAD_LEN, tlv->value_, tlv->len_) !=
67             EOK) {
68             *retCode = TLV_ERR_BUFF_NO_ENOUGH;
69             return nullptr;
70         }
71     }
72     *retCode = TLV_OK;
73     return GetNextTlv(buffer);
74 }
75 
Serialize(const TlvCommon * tlv,uint32_t tlvCount,uint8_t * buff,uint32_t maxBuffSize,uint32_t * buffSize)76 uint32_t TlvUtils::Serialize(const TlvCommon *tlv, uint32_t tlvCount, uint8_t *buff, uint32_t maxBuffSize,
77                              uint32_t *buffSize)
78 {
79     if (tlv == nullptr || buff == nullptr || buffSize == nullptr) {
80         return TLV_ERR_INVALID_PARA;
81     }
82     uint8_t *curr = buff;
83     uint8_t *boundary = buff + maxBuffSize;
84 
85     uint32_t retCode = TLV_OK;
86     for (uint32_t index = 0; index < tlvCount; index++) {
87         curr = AppendTlv(curr, &tlv[index], boundary, &retCode);
88         if (curr == nullptr || retCode != TLV_OK) {
89             return retCode;
90         }
91     }
92     *buffSize = curr - buff;
93     return TLV_OK;
94 }
95 
Deserialize(const uint8_t * buff,uint32_t buffSize,TlvCommon * tlv,uint32_t maxTlvCount,uint32_t * tlvCount)96 uint32_t TlvUtils::Deserialize(const uint8_t *buff, uint32_t buffSize, TlvCommon *tlv, uint32_t maxTlvCount,
97                                uint32_t *tlvCount)
98 {
99     if (tlv == nullptr || buff == nullptr || tlvCount == nullptr) {
100         return TLV_ERR_INVALID_PARA;
101     }
102 
103     auto *msg = const_cast<uint8_t *>(buff);
104     const uint8_t *boundary = buff + buffSize;
105     uint32_t index = 0;
106 
107     while (msg != nullptr) {
108         if (index >= maxTlvCount) {
109             return TLV_ERR_BUFF_NO_ENOUGH;
110         }
111         uint32_t retCode = TLV_OK;
112         msg = ParseTlv(msg, &tlv[index], boundary, &retCode);
113         if (msg == nullptr || retCode != TLV_OK) {
114             break;
115         }
116         index++;
117     }
118     *tlvCount = index;
119     return TLV_OK;
120 }
121 
GenerateTlv(DfxMessage & msg,TlvCommon * tlvs,uint32_t * tlvCount)122 uint32_t TlvUtils::GenerateTlv(DfxMessage &msg, TlvCommon *tlvs, uint32_t *tlvCount)
123 {
124     uint32_t index = 0;
125     tlvs[index++] = TlvCommon{U64, sizeof(msg.requestBeginTime_), &msg.requestBeginTime_};
126     tlvs[index++] = TlvCommon{U64, sizeof(msg.dnsEndTime_), &msg.dnsEndTime_};
127     tlvs[index++] = TlvCommon{U64, sizeof(msg.tcpConnectEndTime_), &msg.tcpConnectEndTime_};
128     tlvs[index++] = TlvCommon{U64, sizeof(msg.tlsHandshakeEndTime_), &msg.tlsHandshakeEndTime_};
129     tlvs[index++] = TlvCommon{U64, sizeof(msg.firstSendTime_), &msg.firstSendTime_};
130     tlvs[index++] = TlvCommon{U64, sizeof(msg.firstRecvTime_), &msg.firstRecvTime_};
131     tlvs[index++] = TlvCommon{U64, sizeof(msg.requestEndTime_), &msg.requestEndTime_};
132     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.requestId_.size()),
133                               const_cast<char *>(msg.requestId_.data())};
134     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.requestUrl_.size()),
135                               const_cast<char *>(msg.requestUrl_.data())};
136     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.requestMethod_.size()),
137                               const_cast<char *>(msg.requestMethod_.data())};
138     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.requestHeader_.size()),
139                               const_cast<char *>(msg.requestHeader_.data())};
140     tlvs[index++] = TlvCommon{U32, sizeof(msg.responseStatusCode_), &msg.responseStatusCode_};
141     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseHeader_.size()),
142                               const_cast<char *>(msg.responseHeader_.data())};
143     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseEffectiveUrl_.size()),
144                               const_cast<char *>(msg.responseEffectiveUrl_.data())};
145     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseIpAddress_.size()),
146                               const_cast<char *>(msg.responseIpAddress_.data())};
147     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseHttpVersion_.size()),
148                               const_cast<char *>(msg.responseHttpVersion_.data())};
149     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseReasonPhrase_.size()),
150                               const_cast<char *>(msg.responseReasonPhrase_.data())};
151     tlvs[index++] = TlvCommon{STRING, static_cast<uint32_t>(msg.responseBody_.size()),
152                               const_cast<char *>(msg.responseBody_.data())};
153     *tlvCount = index;
154     return TLV_OK;
155 }
156 
Parse(DfxMessage & msg,TlvCommon * tlvs,uint32_t tlvCount)157 uint32_t TlvUtils::Parse(DfxMessage &msg, TlvCommon *tlvs, uint32_t tlvCount)
158 {
159     uint32_t index = 0;
160     msg.requestBeginTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
161     msg.dnsEndTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
162     msg.tcpConnectEndTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
163     msg.tlsHandshakeEndTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
164     msg.firstSendTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
165     msg.firstRecvTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
166     msg.requestEndTime_ = *(static_cast<uint64_t *>(tlvs[index++].value_));
167     msg.requestId_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
168     index++;
169     msg.requestUrl_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
170     index++;
171     msg.requestMethod_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
172     index++;
173     msg.requestHeader_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
174     index++;
175     msg.responseStatusCode_ = *(static_cast<uint32_t *>(tlvs[index].value_));
176     index++;
177     msg.responseHeader_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
178     index++;
179     msg.responseEffectiveUrl_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
180     index++;
181     msg.responseIpAddress_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
182     index++;
183     msg.responseHttpVersion_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
184     index++;
185     msg.responseReasonPhrase_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
186     index++;
187     msg.responseBody_ = std::string(static_cast<char *>(tlvs[index].value_), tlvs[index].len_);
188     index++;
189     if (index != tlvCount) {
190         return TLV_ERR_PARSE_PAYLOAD_ERR;
191     }
192     return TLV_OK;
193 }
194 
Encode(DfxMessage & msg,void * data,uint32_t & dataSize)195 uint32_t TlvUtils::Encode(DfxMessage &msg, void *data, uint32_t &dataSize)
196 {
197     void *tlvsTemp = malloc(sizeof(TlvCommon) * DFX_MSG_FIELD_NUM);
198     if (tlvsTemp == nullptr) {
199         NETSTACK_LOGE("tlv encode malloc tlvList failed");
200         return TLV_ERR;
201     }
202     auto *tlvs = static_cast<TlvCommon *>(tlvsTemp);
203     (void) memset_s(&tlvs[0], sizeof(TlvCommon) * DFX_MSG_FIELD_NUM, 0,
204                     sizeof(TlvCommon) * DFX_MSG_FIELD_NUM);
205     uint32_t fieldCount = 0;
206     GenerateTlv(msg, tlvs, &fieldCount);
207 
208     if (data == nullptr) {
209         data = malloc(BUFFER_MAX_SIZE);
210         if (data == nullptr) {
211             NETSTACK_LOGE("tlv encode malloc data failed");
212             free(tlvsTemp);
213             return TLV_ERR;
214         }
215     }
216     (void) memset_s(data, BUFFER_MAX_SIZE, 0, BUFFER_MAX_SIZE);
217     uint32_t ret = Serialize(tlvs, fieldCount, static_cast<uint8_t *>(data), BUFFER_MAX_SIZE,
218                              &dataSize);
219     free(tlvsTemp);
220     NETSTACK_LOGI("tlv encode finished. code=%{public}u", ret);
221     return ret;
222 }
223 
Decode(DfxMessage & msg,void * data,uint32_t dataSize)224 uint32_t TlvUtils::Decode(DfxMessage &msg, void *data, uint32_t dataSize)
225 {
226     if (data == nullptr || dataSize == 0) {
227         NETSTACK_LOGE("tlv decode invalid params");
228         return TLV_ERR_INVALID_PARA;
229     }
230     void *tlvsTemp = malloc(sizeof(TlvCommon) * DFX_MSG_FIELD_NUM);
231     if (tlvsTemp == nullptr) {
232         NETSTACK_LOGE("tlv decode malloc tlvList failed");
233         return TLV_ERR;
234     }
235     auto *tlvs = static_cast<TlvCommon *>(tlvsTemp);
236     (void) memset_s(&tlvs[0], sizeof(TlvCommon) * DFX_MSG_FIELD_NUM, 0,
237                     sizeof(TlvCommon) * DFX_MSG_FIELD_NUM);
238     uint32_t fieldCount = 0;
239     auto ret = Deserialize(static_cast<uint8_t *>(data), dataSize, tlvs, DFX_MSG_FIELD_NUM, &fieldCount);
240     Parse(msg, tlvs, fieldCount);
241     free(tlvsTemp);
242     NETSTACK_LOGI("tlv decode finished. code=%{public}u", ret);
243     return ret;
244 }
245 }