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 int32_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,int32_t length)55 void TlvItem::Initialize(const void* data, int32_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,int32_t length)104 TlvItem::TlvItem(int32_t type, const unsigned char* value, int32_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 value = ntohl((*(int32_t*)(iter->second->GetValue())));
173 return true;
174 }
175 return false;
176 }
177
GetInt64Value(int32_t type,int64_t & value)178 bool TlvBox::GetInt64Value(int32_t type, int64_t& value)
179 {
180 auto iter = TlvMap_.find(type);
181 if (iter != TlvMap_.end()) {
182 value = static_cast<int64_t>(Ntohll((*(uint64_t*)(iter->second->GetValue()))));
183 return true;
184 }
185 return false;
186 }
187
GetObjectValue(int32_t type,TlvBox & value)188 bool TlvBox::GetObjectValue(int32_t type, TlvBox& value)
189 {
190 auto iter = TlvMap_.find(type);
191 if (iter == TlvMap_.end()) {
192 return false;
193 }
194 return value.Parse(iter->second->GetValue(), iter->second->GetLength());
195 }
196
Parse(const unsigned char * buffer,int32_t buffersize)197 bool TlvBox::Parse(const unsigned char* buffer, int32_t buffersize)
198 {
199 if (buffer == NULL) {
200 return false;
201 }
202
203 if (buffersize > MAX_BUFFER_LENGTH) {
204 ANS_LOGW("Parse data length invalid %{public}d", buffersize);
205 return false;
206 }
207 unsigned char* cached = new unsigned char[buffersize];
208 errno_t err = memcpy_s(cached, buffersize, buffer, buffersize);
209 if (err != EOK) {
210 delete[] cached;
211 return false;
212 }
213
214 int offset = 0;
215 while (offset < buffersize) {
216 int32_t type = ntohl((*(int32_t*)(cached + offset)));
217 offset += sizeof(int32_t);
218 int32_t length = ntohl((*(int32_t*)(cached + offset)));
219 offset += sizeof(int32_t);
220 PutValue(std::make_shared<TlvItem>(type, cached + offset, length));
221 offset += length;
222 }
223
224 delete[] cached;
225 bytesLength_ = buffersize;
226 delete[] cached;
227 return true;
228 }
229
Serialize(bool addCheck)230 bool TlvBox::Serialize(bool addCheck)
231 {
232 int offset = 0;
233 int32_t bytesLeft = bytesLength_;
234 if (addCheck) {
235 bytesLength_ = bytesLength_ + sizeof(uint32_t);
236 }
237 if (bytesLength_ > MAX_BUFFER_LENGTH) {
238 ANS_LOGW("Serialize data length invalid %{public}d", bytesLength_);
239 return false;
240 }
241 byteBuffer_ = new unsigned char[bytesLength_];
242 for (auto iter = TlvMap_.begin(); iter != TlvMap_.end(); iter++) {
243 int32_t type = htonl(iter->second->GetType());
244 errno_t err = memcpy_s(byteBuffer_ + offset, bytesLeft, &type, sizeof(int32_t));
245 if (err != EOK) {
246 delete[] byteBuffer_;
247 byteBuffer_ = nullptr;
248 return false;
249 }
250 offset += sizeof(int32_t);
251 bytesLeft -= sizeof(int32_t);
252 int32_t length = iter->second->GetLength();
253 int32_t lengthValue = htonl(length);
254 err = memcpy_s(byteBuffer_ + offset, bytesLeft, &lengthValue, sizeof(int32_t));
255 if (err != EOK) {
256 delete[] byteBuffer_;
257 byteBuffer_ = nullptr;
258 return false;
259 }
260 offset += sizeof(int32_t);
261 bytesLeft -= sizeof(int32_t);
262 err = memcpy_s(byteBuffer_ + offset, bytesLeft, iter->second->GetValue(), length);
263 if (err != EOK) {
264 delete[] byteBuffer_;
265 byteBuffer_ = nullptr;
266 return false;
267 }
268 offset += length;
269 bytesLeft -= length;
270 }
271 if (addCheck) {
272 uint32_t calCrc = crc32(crc32(0L, Z_NULL, 0), (const Bytef*)byteBuffer_, offset);
273 uint32_t calValue = htonl(calCrc);
274 (void)memcpy_s(byteBuffer_ + offset, sizeof(uint32_t), &calValue, sizeof(uint32_t));
275 ANS_LOGI("Box Serialize crc32 %{public}d %{public}d.", (int32_t)(offset + sizeof(uint32_t)), (int32_t)(calCrc));
276 } else {
277 ANS_LOGI("Box Serialize crc32 %{public}d.", offset);
278 }
279 return true;
280 }
281
SetMessageType(int32_t messageType)282 bool TlvBox::SetMessageType(int32_t messageType)
283 {
284 return PutValue(std::make_shared<TlvItem>(MESSAGE_TYPE_ID, messageType));
285 }
286
CheckMessageCRC(const unsigned char * data,uint32_t dataLen)287 bool TlvBox::CheckMessageCRC(const unsigned char*data, uint32_t dataLen)
288 {
289 uint32_t calcSize = sizeof(uint32_t);
290 if (dataLen <= calcSize || dataLen > MAX_BUFFER_LENGTH) {
291 ANS_LOGW("Box check length failed %{public}d.", (int32_t)(dataLen));
292 return false;
293 }
294 uint32_t recv = ntohl((*(uint32_t*)(data + dataLen - calcSize)));
295 uint32_t calc = crc32(crc32(0L, Z_NULL, 0), (const Bytef*)data, dataLen - calcSize);
296 if (calc != recv) {
297 ANS_LOGW("Box check crc32 failed %{public}d %{public}d.", (int32_t)(recv), (int32_t)(calc));
298 return false;
299 }
300 return true;
301 }
302
303 }
304 }
305