• 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 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