• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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