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 #include "tlv_box.h"
16
17 #include <securec.h>
18 #include <arpa/inet.h>
19 #include "ans_log_wrapper.h"
20 #include "zlib.h"
21
22 namespace OHOS {
23 namespace Notification {
24
25 namespace {
26 constexpr int32_t MAX_BUFFER_LENGTH = 1024 * 4 * 1024;
27 constexpr int32_t INT_LENGTH = 32;
28 }
29
Htonll(uint64_t value)30 uint64_t Htonll(uint64_t value)
31 {
32 return ((static_cast<uint64_t>(htonl(value))) << INT_LENGTH) + htonl(value >> INT_LENGTH);
33 }
34
Ntohll(uint64_t value)35 uint64_t Ntohll(uint64_t value)
36 {
37 return ((static_cast<uint64_t>(ntohl(value))) << INT_LENGTH) + ntohl(value >> INT_LENGTH);
38 }
39
GetType() const40 int32_t TlvItem::GetType() const
41 {
42 return type_;
43 }
44
GetLength() const45 uint32_t TlvItem::GetLength() const
46 {
47 return length_;
48 }
49
GetValue() const50 unsigned char* TlvItem::GetValue() const
51 {
52 return value_;
53 }
54
Initialize(const void * data,uint32_t length)55 void TlvItem::Initialize(const void* data, uint32_t length)
56 {
57 if (length > MAX_BUFFER_LENGTH) {
58 ANS_LOGW("Initialize data invalid %{public}d %{public}d %{public}d", type_, length, length_);
59 return;
60 }
61 length_ = length;
62 value_ = new unsigned char[length];
63 errno_t err = memcpy_s(value_, length, data, length);
64 if (err != EOK) {
65 ANS_LOGW("tlv item copy failed.");
66 }
67 }
68
~TlvItem()69 TlvItem::~TlvItem()
70 {
71 if (value_ != nullptr) {
72 delete[] value_;
73 value_ = nullptr;
74 }
75 }
76
TlvItem(int32_t type,bool value)77 TlvItem::TlvItem(int32_t type, bool value) : type_(type)
78 {
79 Initialize(&value, sizeof(bool));
80 }
81
TlvItem(int32_t type,int32_t value)82 TlvItem::TlvItem(int32_t type, int32_t value) : type_(type)
83 {
84 int32_t newValue = htonl(value);
85 Initialize(&newValue, sizeof(int32_t));
86 }
87
TlvItem(int32_t type,int64_t value)88 TlvItem::TlvItem(int32_t type, int64_t value) : type_(type)
89 {
90 uint64_t newValue = Htonll(static_cast<uint64_t>(value));
91 Initialize(&newValue, sizeof(uint64_t));
92 }
93
TlvItem(int32_t type,std::string value)94 TlvItem::TlvItem(int32_t type, std::string value) : type_(type)
95 {
96 Initialize(value.c_str(), value.size() + 1);
97 }
98
TlvItem(int32_t type,const TlvItem & value)99 TlvItem::TlvItem(int32_t type, const TlvItem& value) : type_(type)
100 {
101 Initialize(value.GetValue(), value.GetLength());
102 }
103
TlvItem(int32_t type,const unsigned char * value,uint32_t length)104 TlvItem::TlvItem(int32_t type, const unsigned char* value, uint32_t length) : type_(type)
105 {
106 Initialize(value, length);
107 }
108
~TlvBox()109 TlvBox::~TlvBox()
110 {
111 if (byteBuffer_ != NULL) {
112 delete[] byteBuffer_;
113 byteBuffer_ = NULL;
114 }
115 }
116
PutValue(std::shared_ptr<TlvItem> value)117 bool TlvBox::PutValue(std::shared_ptr<TlvItem> value)
118 {
119 auto iter = TlvMap_.find(value->GetType());
120 if (iter != TlvMap_.end()) {
121 std::shared_ptr<TlvItem> item = iter->second;
122 bytesLength_ = bytesLength_ - (sizeof(int32_t) + sizeof(int32_t) + item->GetLength());
123 iter->second = value;
124 } else {
125 TlvMap_.insert(std::pair<int32_t, std::shared_ptr<TlvItem>>(value->GetType(), value));
126 }
127
128 bytesLength_ += (sizeof(int32_t) + sizeof(int32_t) + value->GetLength());
129 return true;
130 }
131
GetMessageType(int32_t & messageType)132 bool TlvBox::GetMessageType(int32_t& messageType)
133 {
134 return GetInt32Value(MESSAGE_TYPE_ID, messageType);
135 }
136
GetBoolValue(int32_t type,bool & value)137 bool TlvBox::GetBoolValue(int32_t type, bool& value)
138 {
139 auto iter = TlvMap_.find(type);
140 if (iter != TlvMap_.end()) {
141 value = (*(bool*)(iter->second->GetValue()));
142 return true;
143 }
144 return false;
145 }
146
GetBytes(int32_t type,std::vector<uint8_t> & value)147 bool TlvBox::GetBytes(int32_t type, std::vector<uint8_t>& value)
148 {
149 auto iter = TlvMap_.find(type);
150 if (iter != TlvMap_.end()) {
151 auto begin = iter->second->GetValue();
152 value.assign(begin, begin + iter->second->GetLength());
153 return true;
154 }
155 return false;
156 }
157
GetStringValue(int32_t type,std::string & value)158 bool TlvBox::GetStringValue(int32_t type, std::string& value)
159 {
160 auto iter = TlvMap_.find(type);
161 if (iter != TlvMap_.end()) {
162 value = reinterpret_cast<char*>(iter->second->GetValue());
163 return true;
164 }
165 return false;
166 }
167
GetInt32Value(int32_t type,int32_t & value)168 bool TlvBox::GetInt32Value(int32_t type, int32_t& value)
169 {
170 auto iter = TlvMap_.find(type);
171 if (iter != TlvMap_.end()) {
172 if (iter->second->GetLength() < sizeof(int32_t)) {
173 ANS_LOGW("Invalid item %{public}d %{public}u.", type, iter->second->GetLength());
174 return false;
175 }
176 value = ntohl((*(int32_t*)(iter->second->GetValue())));
177 return true;
178 }
179 return false;
180 }
181
GetInt64Value(int32_t type,int64_t & value)182 bool TlvBox::GetInt64Value(int32_t type, int64_t& value)
183 {
184 auto iter = TlvMap_.find(type);
185 if (iter != TlvMap_.end()) {
186 if (iter->second->GetLength() < sizeof(uint64_t)) {
187 ANS_LOGW("Invalid item %{public}d %{public}u.", type, iter->second->GetLength());
188 return false;
189 }
190 value = static_cast<int64_t>(Ntohll((*(uint64_t*)(iter->second->GetValue()))));
191 return true;
192 }
193 return false;
194 }
195
GetObjectValue(int32_t type,TlvBox & value)196 bool TlvBox::GetObjectValue(int32_t type, TlvBox& value)
197 {
198 auto iter = TlvMap_.find(type);
199 if (iter == TlvMap_.end()) {
200 return false;
201 }
202 return value.Parse(iter->second->GetValue(), iter->second->GetLength());
203 }
204
Parse(const unsigned char * buffer,uint32_t buffersize)205 bool TlvBox::Parse(const unsigned char* buffer, uint32_t buffersize)
206 {
207 if (buffer == NULL) {
208 return false;
209 }
210
211 if (buffersize > MAX_BUFFER_LENGTH) {
212 ANS_LOGW("Parse data length invalid %{public}d", buffersize);
213 return false;
214 }
215 unsigned char* cached = new unsigned char[buffersize];
216 errno_t err = memcpy_s(cached, buffersize, buffer, buffersize);
217 if (err != EOK) {
218 delete[] cached;
219 return false;
220 }
221
222 uint32_t offset = 0;
223 while (offset < buffersize) {
224 if (offset + sizeof(int32_t) > buffersize) {
225 delete[] cached;
226 return false;
227 }
228 int32_t type = ntohl((*(int32_t*)(cached + offset)));
229 offset += sizeof(int32_t);
230 if (offset + sizeof(int32_t) > buffersize) {
231 delete[] cached;
232 return false;
233 }
234 int32_t length = ntohl((*(int32_t*)(cached + offset)));
235 offset += sizeof(int32_t);
236 if (static_cast<uint32_t>(length) > buffersize ||
237 offset + static_cast<uint32_t>(length) > buffersize) {
238 delete[] cached;
239 return false;
240 }
241 PutValue(std::make_shared<TlvItem>(type, cached + offset, length));
242 offset += length;
243 }
244
245 delete[] cached;
246 bytesLength_ = buffersize;
247 delete[] cached;
248 return true;
249 }
250
Serialize(bool addCheck)251 bool TlvBox::Serialize(bool addCheck)
252 {
253 int offset = 0;
254 int32_t bytesLeft = bytesLength_;
255 if (addCheck) {
256 bytesLength_ = bytesLength_ + sizeof(uint32_t);
257 }
258 if (bytesLength_ > MAX_BUFFER_LENGTH) {
259 ANS_LOGW("Serialize data length invalid %{public}d", bytesLength_);
260 return false;
261 }
262 byteBuffer_ = new unsigned char[bytesLength_];
263 for (auto iter = TlvMap_.begin(); iter != TlvMap_.end(); iter++) {
264 int32_t type = htonl(iter->second->GetType());
265 errno_t err = memcpy_s(byteBuffer_ + offset, bytesLeft, &type, sizeof(int32_t));
266 if (err != EOK) {
267 delete[] byteBuffer_;
268 byteBuffer_ = nullptr;
269 return false;
270 }
271 offset += sizeof(int32_t);
272 bytesLeft -= sizeof(int32_t);
273 int32_t length = iter->second->GetLength();
274 int32_t lengthValue = htonl(length);
275 err = memcpy_s(byteBuffer_ + offset, bytesLeft, &lengthValue, sizeof(int32_t));
276 if (err != EOK) {
277 delete[] byteBuffer_;
278 byteBuffer_ = nullptr;
279 return false;
280 }
281 offset += sizeof(int32_t);
282 bytesLeft -= sizeof(int32_t);
283 err = memcpy_s(byteBuffer_ + offset, bytesLeft, iter->second->GetValue(), length);
284 if (err != EOK) {
285 delete[] byteBuffer_;
286 byteBuffer_ = nullptr;
287 return false;
288 }
289 offset += length;
290 bytesLeft -= length;
291 }
292 if (addCheck) {
293 uint32_t calCrc = crc32(crc32(0L, Z_NULL, 0), (const Bytef*)byteBuffer_, offset);
294 uint32_t calValue = htonl(calCrc);
295 (void)memcpy_s(byteBuffer_ + offset, sizeof(uint32_t), &calValue, sizeof(uint32_t));
296 ANS_LOGI("Box Serialize crc32 %{public}d %{public}d.", (int32_t)(offset + sizeof(uint32_t)), (int32_t)(calCrc));
297 } else {
298 ANS_LOGI("Box Serialize crc32 %{public}d.", offset);
299 }
300 return true;
301 }
302
SetMessageType(int32_t messageType)303 bool TlvBox::SetMessageType(int32_t messageType)
304 {
305 return PutValue(std::make_shared<TlvItem>(MESSAGE_TYPE_ID, messageType));
306 }
307
CheckMessageCRC(const unsigned char * data,uint32_t dataLen)308 bool TlvBox::CheckMessageCRC(const unsigned char*data, uint32_t dataLen)
309 {
310 uint32_t calcSize = sizeof(uint32_t);
311 if (dataLen <= calcSize || dataLen > MAX_BUFFER_LENGTH) {
312 ANS_LOGW("Box check length failed %{public}d.", (int32_t)(dataLen));
313 return false;
314 }
315 uint32_t recv = ntohl((*(uint32_t*)(data + dataLen - calcSize)));
316 uint32_t calc = crc32(crc32(0L, Z_NULL, 0), (const Bytef*)data, dataLen - calcSize);
317 if (calc != recv) {
318 ANS_LOGW("Box check crc32 failed %{public}d %{public}d.", (int32_t)(recv), (int32_t)(calc));
319 return false;
320 }
321 return true;
322 }
323
324 }
325 }
326