1 /*
2 * Copyright (C) 2023 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 "gsm_user_data_decode.h"
17
18 #include "gsm_pdu_hex_value.h"
19 #include "gsm_sms_common_utils.h"
20 #include "securec.h"
21 #include "telephony_log_wrapper.h"
22
23 namespace OHOS {
24 namespace Telephony {
25 using namespace std;
26 static constexpr uint8_t GSM_USER_DATA_LEN = 160;
27 static constexpr uint8_t NORMAL_BYTE_BITS = 8;
28 static constexpr uint8_t GSM_ENCODE_BITS = 7;
29 static constexpr uint8_t SLIDE_DATA_STEP = 2;
30 static constexpr uint8_t UCS2_USER_DATA_LEN = 140;
31 static constexpr uint8_t WAP_PUSH_UDHL = 7;
32
GsmUserDataDecode(std::shared_ptr<GsmUserDataPdu> data)33 GsmUserDataDecode::GsmUserDataDecode(std::shared_ptr<GsmUserDataPdu> data)
34 {
35 userData_ = data;
36 }
37
~GsmUserDataDecode()38 GsmUserDataDecode::~GsmUserDataDecode() {}
39
DecodeGsmPdu(SmsReadBuffer & buffer,bool bHeaderInd,struct SmsUDPackage * userData,struct SmsTpud * pTPUD)40 bool GsmUserDataDecode::DecodeGsmPdu(
41 SmsReadBuffer &buffer, bool bHeaderInd, struct SmsUDPackage *userData, struct SmsTpud *pTPUD)
42 {
43 uint8_t udl = 0;
44 uint8_t fillBits = 0;
45 if (!DecodeGsmHeadPdu(buffer, bHeaderInd, userData, pTPUD, udl, fillBits)) {
46 TELEPHONY_LOGE("decode gsm head error");
47 return false;
48 }
49 return DecodeGsmBodyPdu(buffer, bHeaderInd, userData, pTPUD, udl, fillBits);
50 }
51
DecodeGsmHeadPdu(SmsReadBuffer & buffer,bool bHeaderInd,struct SmsUDPackage * userData,struct SmsTpud * pTPUD,uint8_t & udl,uint8_t & fillBits)52 bool GsmUserDataDecode::DecodeGsmHeadPdu(SmsReadBuffer &buffer, bool bHeaderInd, struct SmsUDPackage *userData,
53 struct SmsTpud *pTPUD, uint8_t &udl, uint8_t &fillBits)
54 {
55 if (userData == nullptr) {
56 TELEPHONY_LOGE("nullptr error");
57 return false;
58 }
59
60 /* UDL */
61 if (!buffer.ReadByte(udl)) {
62 TELEPHONY_LOGE("get data error.");
63 return false;
64 }
65 if (udl > GSM_USER_DATA_LEN) {
66 userData->length = 0;
67 userData->headerCnt = 0;
68 TELEPHONY_LOGE("udl error.");
69 return false;
70 }
71
72 /* Setting for Wap Push */
73 if (pTPUD != nullptr && udl > 0) {
74 pTPUD->udl = udl;
75 if (udl > sizeof(pTPUD->ud)) {
76 TELEPHONY_LOGE("udl length error");
77 return false;
78 }
79 uint8_t len = udl;
80 if (buffer.GetIndex() + udl >= buffer.GetSize()) {
81 len = buffer.GetSize() - buffer.GetIndex();
82 }
83 if (buffer.data_ == nullptr || len > sizeof(pTPUD->ud)) {
84 TELEPHONY_LOGE("buffer error.");
85 return false;
86 }
87 if (memcpy_s(pTPUD->ud, sizeof(pTPUD->ud), buffer.data_.get() + buffer.GetIndex(), len) != EOK) {
88 TELEPHONY_LOGE("memcpy_s error");
89 return false;
90 }
91 pTPUD->ud[len] = '\0';
92 }
93 return DecodeGsmHeadPduPartData(buffer, bHeaderInd, userData, udl, fillBits);
94 }
95
DecodeGsmHeadPduPartData(SmsReadBuffer & buffer,bool bHeaderInd,struct SmsUDPackage * userData,uint8_t & udl,uint8_t & fillBits)96 bool GsmUserDataDecode::DecodeGsmHeadPduPartData(
97 SmsReadBuffer &buffer, bool bHeaderInd, struct SmsUDPackage *userData, uint8_t &udl, uint8_t &fillBits)
98 {
99 if (userData_ == nullptr) {
100 TELEPHONY_LOGE("nullptr error.");
101 return false;
102 }
103 uint8_t udhl = 0;
104 /* Decode User Data Header */
105 if (bHeaderInd) {
106 /* UDHL */
107 if (!buffer.ReadByte(udhl)) {
108 TELEPHONY_LOGE("get data error.");
109 return false;
110 }
111 userData->headerCnt = 0;
112 uint8_t current = buffer.GetIndex();
113 for (int i = 0; buffer.GetIndex() < current + udhl && i < MAX_UD_HEADER_NUM; i++) {
114 uint16_t headerLen = 0;
115 if (!userData_->DecodeHeader(buffer, userData->header[i], headerLen)) {
116 TELEPHONY_LOGE("DecodeHeader error");
117 return false;
118 }
119 if (headerLen == 0) {
120 userData_->ResetUserData(*userData);
121 TELEPHONY_LOGE("headerLen error");
122 return false;
123 }
124 if (buffer.GetIndex() > buffer.GetSize()) {
125 TELEPHONY_LOGE("data buffer error)");
126 userData_->ResetUserData(*userData);
127 return false;
128 }
129 userData->headerCnt++;
130 }
131 } else {
132 userData->headerCnt = 0;
133 }
134
135 if (udhl > 0) {
136 fillBits = ((udl * GSM_ENCODE_BITS) - ((udhl + 1) * NORMAL_BYTE_BITS)) % GSM_ENCODE_BITS;
137 udl = ((udl * GSM_ENCODE_BITS) - ((udhl + 1) * NORMAL_BYTE_BITS)) / GSM_ENCODE_BITS;
138 }
139 return true;
140 }
141
DecodeGsmBodyPdu(SmsReadBuffer & buffer,bool bHeaderInd,struct SmsUDPackage * userData,struct SmsTpud * pTPUD,uint8_t & udl,uint8_t fillBits)142 bool GsmUserDataDecode::DecodeGsmBodyPdu(SmsReadBuffer &buffer, bool bHeaderInd, struct SmsUDPackage *userData,
143 struct SmsTpud *pTPUD, uint8_t &udl, uint8_t fillBits)
144 {
145 if (userData == nullptr) {
146 TELEPHONY_LOGE("nullptr error.");
147 return false;
148 }
149
150 GsmSmsCommonUtils utils;
151 uint8_t length = 0;
152 bool ret = utils.Unpack7bitChar(
153 buffer, udl, fillBits, reinterpret_cast<uint8_t *>(userData->data), MAX_USER_DATA_LEN + 1, length);
154 if (ret) {
155 userData->length = length;
156 }
157 TELEPHONY_LOGI("decode gsm body result:%{public}d", ret);
158 return ret;
159 }
160
Decode8bitPdu(SmsReadBuffer & buffer,bool bHeaderInd,struct SmsUDPackage * userData,struct SmsTpud * pTPUD)161 bool GsmUserDataDecode::Decode8bitPdu(
162 SmsReadBuffer &buffer, bool bHeaderInd, struct SmsUDPackage *userData, struct SmsTpud *pTPUD)
163 {
164 if (userData == nullptr) {
165 TELEPHONY_LOGE("nullptr error.");
166 return false;
167 }
168 /* UDL */
169 uint8_t udl = 0;
170 if (!buffer.ReadByte(udl)) {
171 TELEPHONY_LOGE("get data error.");
172 return false;
173 }
174 TELEPHONY_LOGI("udl:%{public}d", udl);
175 uint16_t current = buffer.GetIndex();
176
177 if (udl > UCS2_USER_DATA_LEN) {
178 userData->length = 0;
179 TELEPHONY_LOGE("udl length error");
180 return false;
181 }
182 uint8_t udhl = 0;
183 if (!buffer.PickOneByte(udhl)) {
184 TELEPHONY_LOGE("get udhl error, use original value: 6");
185 udhl = WAP_PUSH_UDHL - 1;
186 }
187 /* Setting for Wap Push */
188 if (pTPUD != nullptr && udl > (udhl + 1)) {
189 pTPUD->udl = udl - (udhl + 1);
190 if (pTPUD->udl >= sizeof(pTPUD->ud)) {
191 TELEPHONY_LOGE("udl length error");
192 return false;
193 }
194
195 if (buffer.data_ == nullptr || (buffer.GetIndex() + pTPUD->udl + (udhl + 1) > buffer.GetSize())) {
196 TELEPHONY_LOGE("buffer error.");
197 return false;
198 }
199 if (memcpy_s(pTPUD->ud, sizeof(pTPUD->ud), buffer.data_.get() + buffer.GetIndex() + (udhl + 1),
200 pTPUD->udl) != EOK) {
201 TELEPHONY_LOGE("memcpy_s error.");
202 return false;
203 }
204 pTPUD->ud[pTPUD->udl] = '\0';
205 }
206 return Decode8bitPduPartData(buffer, bHeaderInd, userData, pTPUD, current, udl);
207 }
208
Decode8bitPduPartData(SmsReadBuffer & buffer,bool bHeaderInd,struct SmsUDPackage * userData,struct SmsTpud * pTPUD,uint16_t current,uint8_t udl)209 bool GsmUserDataDecode::Decode8bitPduPartData(SmsReadBuffer &buffer, bool bHeaderInd, struct SmsUDPackage *userData,
210 struct SmsTpud *pTPUD, uint16_t current, uint8_t udl)
211 {
212 if (userData_ == nullptr) {
213 TELEPHONY_LOGE("nullptr error.");
214 return false;
215 }
216
217 uint8_t udhl = 0;
218 /* Decode User Data Header */
219 if (bHeaderInd) {
220 /* UDHL */
221 if (!buffer.ReadByte(udhl)) {
222 TELEPHONY_LOGE("get data error.");
223 return false;
224 }
225 userData->headerCnt = 0;
226 current = buffer.GetIndex();
227 for (uint8_t i = 0; (buffer.GetIndex() - current) < udhl && i < MAX_UD_HEADER_NUM; i++) {
228 if (!userData_->GetHeaderCnt(buffer, userData, udhl, i)) {
229 TELEPHONY_LOGI("data error");
230 return false;
231 }
232 }
233 } else {
234 userData->headerCnt = 0;
235 }
236
237 if (udhl > 0 && udl >= udhl + 1) {
238 userData->length = (udl) - (udhl + 1);
239 buffer.MoveForward(HEX_VALUE_01);
240 } else {
241 userData->length = udl;
242 }
243 if (udl > sizeof(pTPUD->ud) || buffer.GetIndex() > buffer.GetSize()) {
244 TELEPHONY_LOGE("udl length or buffer error");
245 return false;
246 }
247 uint8_t remain = buffer.GetSize() - buffer.GetIndex();
248 uint8_t len = userData->length < remain ? userData->length : remain;
249 if (len == 0) {
250 TELEPHONY_LOGI("user data length 0.");
251 return true;
252 }
253 if (buffer.data_ == nullptr || len > sizeof(userData->data)) {
254 TELEPHONY_LOGE("buffer error.");
255 return false;
256 }
257 if (memcpy_s(userData->data, sizeof(userData->data), buffer.data_.get() + buffer.GetIndex(), len) != EOK) {
258 TELEPHONY_LOGE("memcpy_s error");
259 return false;
260 }
261 buffer.MoveForward(userData->length);
262 return true;
263 }
264
DecodeUcs2Pdu(SmsReadBuffer & buffer,bool bHeaderInd,struct SmsUDPackage * userData,struct SmsTpud * pTPUD)265 bool GsmUserDataDecode::DecodeUcs2Pdu(
266 SmsReadBuffer &buffer, bool bHeaderInd, struct SmsUDPackage *userData, struct SmsTpud *pTPUD)
267 {
268 if (userData == nullptr) {
269 TELEPHONY_LOGE("nullptr error.");
270 return false;
271 }
272 uint16_t current = buffer.GetIndex();
273
274 /* UDL */
275 uint8_t udl = 0;
276 if (!buffer.ReadByte(udl)) {
277 TELEPHONY_LOGE("get data error.");
278 return false;
279 }
280 if (udl > UCS2_USER_DATA_LEN || (udl + buffer.GetIndex() - 1) > buffer.GetSize()) {
281 TELEPHONY_LOGE("udl error.");
282 userData->length = 0;
283 userData->headerCnt = 0;
284 return false;
285 }
286 if (buffer.data_ == nullptr) {
287 TELEPHONY_LOGE("buffer error.");
288 return false;
289 }
290 /* Setting for Wap Push */
291 if (pTPUD != nullptr) {
292 pTPUD->udl = udl;
293 if (udl > sizeof(pTPUD->ud) || (buffer.GetIndex() + udl) > buffer.GetSize()) {
294 TELEPHONY_LOGE("udl error.");
295 return false;
296 }
297 if (memcpy_s(pTPUD->ud, sizeof(pTPUD->ud), buffer.data_.get() + buffer.GetIndex(), udl) != EOK) {
298 TELEPHONY_LOGE("memcpy_s error.");
299 return false;
300 }
301 pTPUD->ud[udl] = '\0';
302 }
303 return DecodeUcs2PduPartData(buffer, bHeaderInd, userData, current, udl);
304 }
305
DecodeUcs2PduPartData(SmsReadBuffer & buffer,bool bHeaderInd,struct SmsUDPackage * userData,uint16_t current,uint8_t udl)306 bool GsmUserDataDecode::DecodeUcs2PduPartData(
307 SmsReadBuffer &buffer, bool bHeaderInd, struct SmsUDPackage *userData, uint16_t current, uint8_t udl)
308 {
309 if (userData_ == nullptr) {
310 TELEPHONY_LOGE("nullptr error.");
311 return false;
312 }
313 uint8_t udhl = 0;
314 userData->headerCnt = 0;
315 /* Decode User Data Header */
316 if (bHeaderInd == true) {
317 /* UDHL */
318 if (!buffer.ReadByte(udhl)) {
319 TELEPHONY_LOGE("get data error.");
320 return false;
321 }
322 for (uint8_t i = 0; buffer.GetIndex() < udhl + current && i < MAX_UD_HEADER_NUM; i++) {
323 uint16_t headerLen;
324 if (!userData_->DecodeHeader(buffer, userData->header[i], headerLen)) {
325 TELEPHONY_LOGE("DecodeHeader error");
326 return false;
327 }
328 if (headerLen == 0 || buffer.GetIndex() > (current + udhl + SLIDE_DATA_STEP)) {
329 userData_->ResetUserData(*userData);
330 return false;
331 }
332 userData->headerCnt++;
333 }
334 }
335
336 if (udhl > 0 && udl >= udhl + 1) {
337 userData->length = (udl) - (udhl + 1);
338 } else {
339 userData->length = udl;
340 }
341
342 if (buffer.GetIndex() > buffer.GetSize()) {
343 TELEPHONY_LOGE("udl length or buffer error");
344 return false;
345 }
346 uint8_t remain = buffer.GetSize() - buffer.GetIndex();
347 uint8_t len = userData->length < remain ? userData->length : remain;
348 if (len == 0) {
349 return true;
350 }
351 if (buffer.data_ == nullptr || len > sizeof(userData->data)) {
352 return false;
353 }
354 if (memcpy_s(userData->data, sizeof(userData->data), buffer.data_.get() + buffer.GetIndex(), len) != EOK) {
355 return false;
356 }
357
358 buffer.MoveForward(userData->length);
359 uint8_t index = userData->length >= sizeof(userData->data) ? sizeof(userData->data) - 1 : userData->length;
360 userData->data[index] = 0;
361 return true;
362 }
363 } // namespace Telephony
364 } // namespace OHOS