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_sms_common_utils.h"
17 
18 #include <ctime>
19 
20 #include "gsm_pdu_hex_value.h"
21 #include "securec.h"
22 #include "telephony_log_wrapper.h"
23 #include "text_coder.h"
24 
25 namespace OHOS {
26 namespace Telephony {
27 static constexpr uint8_t DIGITAL_STEP = 2;
28 static constexpr uint8_t SMS_ENCODE_GSM_BIT = 7;
29 static constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160;
30 static constexpr uint8_t SMS_BYTE_BIT = 8;
31 static constexpr uint8_t MIN_REMAIN_LEN = 2;
32 
Pack7bitChar(SmsWriteBuffer & buffer,const uint8_t * userData,uint8_t dataLen,uint8_t fillBits)33 bool GsmSmsCommonUtils::Pack7bitChar(SmsWriteBuffer &buffer, const uint8_t *userData, uint8_t dataLen, uint8_t fillBits)
34 {
35     if (userData == nullptr || dataLen > MAX_GSM_7BIT_DATA_LEN) {
36         TELEPHONY_LOGE("userData error.");
37         return false;
38     }
39     auto shift = fillBits;
40     if (shift > 0) {
41         buffer.MoveForward(1);
42     }
43     uint8_t srcIdx = 0;
44     while (srcIdx < dataLen) {
45         if (shift == 0) {
46             if (!buffer.WriteByte(userData[srcIdx])) {
47                 TELEPHONY_LOGE("write data error.");
48                 return false;
49             }
50             shift = SMS_ENCODE_GSM_BIT;
51             srcIdx++;
52             if (srcIdx >= dataLen) {
53                 break;
54             }
55         }
56         if (shift > 1) {
57             if (!Pack7bitCharPartData(buffer, userData, srcIdx, shift)) {
58                 TELEPHONY_LOGE("packet fail.");
59                 return false;
60             }
61             shift--;
62             srcIdx++;
63         } else if (shift == 1) {
64             uint8_t oneByte = 0;
65             if (!buffer.GetValueFromIndex(buffer.GetIndex() - 1, oneByte)) {
66                 TELEPHONY_LOGE("get data error.");
67                 return false;
68             }
69             oneByte |= (userData[srcIdx] << shift);
70             if (!buffer.InsertByte(oneByte, (buffer.GetIndex() - 1))) {
71                 TELEPHONY_LOGE("write data error.");
72                 return false;
73             }
74             srcIdx++;
75             shift--;
76         }
77     }
78     return true;
79 }
80 
Pack7bitCharPartData(SmsWriteBuffer & buffer,const uint8_t * userData,uint8_t & srcIdx,uint8_t & shift)81 bool GsmSmsCommonUtils::Pack7bitCharPartData(
82     SmsWriteBuffer &buffer, const uint8_t *userData, uint8_t &srcIdx, uint8_t &shift)
83 {
84     uint8_t oneByte = 0;
85     if (!buffer.GetValueFromIndex(buffer.GetIndex() - 1, oneByte)) {
86         TELEPHONY_LOGE("get data error.");
87         return false;
88     }
89     oneByte |= (userData[srcIdx] << shift);
90     if (!buffer.InsertByte(oneByte, (buffer.GetIndex() - 1))) {
91         TELEPHONY_LOGE("write data error.");
92         return false;
93     }
94     if (!buffer.GetTopValue(oneByte)) {
95         TELEPHONY_LOGE("get data error.");
96         return false;
97     }
98     uint8_t nextByte = userData[srcIdx] >> (SMS_BYTE_BIT - shift);
99     if (!buffer.WriteByte(oneByte | nextByte)) {
100         TELEPHONY_LOGE("write data error.");
101         return false;
102     }
103     return true;
104 }
105 
Unpack7bitChar(SmsReadBuffer & buffer,uint8_t dataLen,uint8_t fillBits,uint8_t * unpackData,uint8_t unpackDataLen,uint8_t & dstIdx)106 bool GsmSmsCommonUtils::Unpack7bitChar(SmsReadBuffer &buffer, uint8_t dataLen, uint8_t fillBits, uint8_t *unpackData,
107     uint8_t unpackDataLen, uint8_t &dstIdx)
108 {
109     auto shift = fillBits;
110     if (unpackData == nullptr || dataLen >= unpackDataLen || fillBits > SMS_BYTE_BIT - 1) {
111         TELEPHONY_LOGE("data error.");
112         return false;
113     }
114     if (shift > 0) {
115         buffer.MoveForward(1);
116     }
117     for (; dstIdx < unpackDataLen; dstIdx++) {
118         if (shift == 0) {
119             uint8_t oneByte = 0;
120             if (!buffer.ReadByte(oneByte)) {
121                 TELEPHONY_LOGI("data unpack finish.");
122                 return true;
123             }
124             unpackData[dstIdx] = oneByte & HEX_VALUE_7F;
125             shift = SMS_ENCODE_GSM_BIT;
126             dstIdx++;
127             if (dstIdx >= unpackDataLen) {
128                 break;
129             }
130         }
131 
132         uint8_t oneByte = 0;
133         if (!buffer.PickOneByteFromIndex(buffer.GetIndex() - 1, oneByte)) {
134             TELEPHONY_LOGI("data unpack finish.");
135             return true;
136         }
137         uint8_t nextByte = 0;
138         if (!buffer.PickOneByte(nextByte)) {
139             TELEPHONY_LOGI("data unpack finish.");
140             unpackData[dstIdx] = (oneByte >> shift);
141             if (unpackData[dstIdx] != 0) {
142                 dstIdx++;
143             }
144             return true;
145         }
146         unpackData[dstIdx] = (oneByte >> shift) + (nextByte << (SMS_BYTE_BIT - shift));
147         unpackData[dstIdx] &= HEX_VALUE_7F;
148         shift--;
149         if (shift > 0) {
150             buffer.MoveForward(1);
151         }
152     }
153     return true;
154 }
155 
Unpack7bitCharForMiddlePart(const uint8_t * buffer,uint8_t dataLen,uint8_t * unpackData)156 bool GsmSmsCommonUtils::Unpack7bitCharForMiddlePart(const uint8_t *buffer, uint8_t dataLen, uint8_t *unpackData)
157 {
158     if (buffer == nullptr || unpackData == nullptr || dataLen <= 0) {
159         TELEPHONY_LOGE("data error.");
160         return false;
161     }
162     uint8_t maxAddressArrayIndex = 19;
163     bool flag = false;
164     for (uint8_t i = 0; i < dataLen; i++) {
165         uint8_t bitOffsetNumber = HEX_VALUE_07 * i;
166         uint8_t shiftNumber = bitOffsetNumber % HEX_VALUE_08;
167         uint8_t byteOffsetNumber = bitOffsetNumber / HEX_VALUE_08;
168         uint8_t currentValue = (HEX_VALUE_7F) & (buffer[byteOffsetNumber] >> shiftNumber);
169         if (shiftNumber > 1) {
170             currentValue &= HEX_VALUE_7F >> (shiftNumber - 1);
171             currentValue |= HEX_VALUE_7F & (buffer[byteOffsetNumber + 1] << (HEX_VALUE_08 - shiftNumber));
172         }
173         if (i > maxAddressArrayIndex) {
174             TELEPHONY_LOGE("Index is over the unpackData length");
175             return false;
176         }
177         if (flag) {
178             if (currentValue == HEX_VALUE_1B) {
179                 unpackData[i] = ' ';
180             } else {
181                 unpackData[i] = TextCoder::Instance().GetUCS2Value(currentValue);
182             }
183             flag = false;
184         } else if (currentValue == HEX_VALUE_1B) {
185             flag = true;
186         } else {
187             unpackData[i] = TextCoder::Instance().GetUCS2Value(currentValue);
188         }
189     }
190     return true;
191 }
192 
DigitToBcd(const char * digit,uint8_t digitLen,uint8_t * bcd,uint8_t bcdLen,uint8_t & len)193 bool GsmSmsCommonUtils::DigitToBcd(const char *digit, uint8_t digitLen, uint8_t *bcd, uint8_t bcdLen, uint8_t &len)
194 {
195     if (digit == nullptr || bcd == nullptr || len >= bcdLen) {
196         TELEPHONY_LOGE("data error.");
197         return false;
198     }
199 
200     len = 0;
201     for (uint8_t i = 0; i < digitLen; i++) {
202         uint8_t temp = static_cast<uint8_t>(digit[i] - '0');
203         if (len >= bcdLen) {
204             TELEPHONY_LOGE("len invalid.");
205             return false;
206         }
207         if ((i % DIGITAL_STEP) == 0) {
208             bcd[len] = temp & HEX_VALUE_0F;
209         } else {
210             bcd[len++] |= ((temp & HEX_VALUE_0F) << HEX_VALUE_04);
211         }
212     }
213 
214     if (len + 1 >= bcdLen) {
215         TELEPHONY_LOGE("len invalid.");
216         return false;
217     }
218     if ((digitLen % DIGITAL_STEP) == 1) {
219         bcd[len++] |= HEX_VALUE_F0;
220     }
221     return true;
222 }
223 
BcdToDigit(const uint8_t * bcd,uint8_t bcdLen,std::string & digit,uint8_t maxDigitLen)224 bool GsmSmsCommonUtils::BcdToDigit(const uint8_t *bcd, uint8_t bcdLen, std::string &digit, uint8_t maxDigitLen)
225 {
226     if (bcd == nullptr || bcdLen == 0 || maxDigitLen == 0) {
227         TELEPHONY_LOGE("data error.");
228         return false;
229     }
230     for (uint8_t i = 0; i < bcdLen; i++) {
231         uint8_t temp = bcd[i] & HEX_VALUE_0F;
232         if (digit.size() + MIN_REMAIN_LEN >= maxDigitLen) {
233             TELEPHONY_LOGE("digit size over max");
234             return false;
235         }
236         digit.push_back(BcdToChar(temp));
237         temp = (bcd[i] & HEX_VALUE_F0) >> HEX_VALUE_04;
238         if (temp == HEX_VALUE_0F) {
239             return true;
240         }
241         digit.push_back(BcdToChar(temp));
242     }
243     return true;
244 }
245 
BcdToChar(const uint8_t c)246 char GsmSmsCommonUtils::BcdToChar(const uint8_t c)
247 {
248     char temp = static_cast<char>(c + '0');
249     return temp;
250 }
251 } // namespace Telephony
252 } // namespace OHOS