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 < dataLen; dstIdx++) {
118 if (shift == 0) {
119 uint8_t oneByte = 0;
120 if (!buffer.ReadByte(oneByte)) {
121 TELEPHONY_LOGE("ReadByte error");
122 return true;
123 }
124 unpackData[dstIdx] = oneByte & HEX_VALUE_7F;
125 shift = SMS_ENCODE_GSM_BIT;
126 dstIdx++;
127 if (dstIdx >= dataLen) {
128 break;
129 }
130 }
131
132 uint8_t oneByte = 0;
133 if (!buffer.PickOneByteFromIndex(buffer.GetIndex() - 1, oneByte)) {
134 TELEPHONY_LOGE("PickOneByteFromIndex error");
135 return true;
136 }
137 if (shift == 1) {
138 unpackData[dstIdx] = (oneByte >> shift);
139 unpackData[dstIdx] &= HEX_VALUE_7F;
140 } else {
141 uint8_t nextByte = 0;
142 if (!buffer.PickOneByte(nextByte)) {
143 TELEPHONY_LOGE("PickOneByte error");
144 return true;
145 }
146 unpackData[dstIdx] = (oneByte >> shift) + (nextByte << (SMS_BYTE_BIT - shift));
147 unpackData[dstIdx] &= HEX_VALUE_7F;
148 }
149 shift--;
150 if (shift > 0) {
151 buffer.MoveForward(1);
152 }
153 }
154 return true;
155 }
156
Unpack7bitCharForMiddlePart(const uint8_t * buffer,uint8_t dataLen,uint8_t * unpackData)157 bool GsmSmsCommonUtils::Unpack7bitCharForMiddlePart(const uint8_t *buffer, uint8_t dataLen, uint8_t *unpackData)
158 {
159 if (buffer == nullptr || unpackData == nullptr || dataLen <= 0) {
160 TELEPHONY_LOGE("data error.");
161 return false;
162 }
163 uint8_t maxAddressArrayIndex = 19;
164 bool flag = false;
165 for (uint8_t i = 0; i < dataLen; i++) {
166 uint8_t bitOffsetNumber = HEX_VALUE_07 * i;
167 uint8_t shiftNumber = bitOffsetNumber % HEX_VALUE_08;
168 uint8_t byteOffsetNumber = bitOffsetNumber / HEX_VALUE_08;
169 uint8_t currentValue = (HEX_VALUE_7F) & (buffer[byteOffsetNumber] >> shiftNumber);
170 if (shiftNumber > 1) {
171 currentValue &= HEX_VALUE_7F >> (shiftNumber - 1);
172 currentValue |= HEX_VALUE_7F & (buffer[byteOffsetNumber + 1] << (HEX_VALUE_08 - shiftNumber));
173 }
174 if (i > maxAddressArrayIndex) {
175 TELEPHONY_LOGE("Index is over the unpackData length");
176 return false;
177 }
178 if (flag) {
179 if (currentValue == HEX_VALUE_1B) {
180 unpackData[i] = ' ';
181 } else {
182 unpackData[i] = TextCoder::Instance().GetUCS2Value(currentValue);
183 }
184 flag = false;
185 } else if (currentValue == HEX_VALUE_1B) {
186 flag = true;
187 } else {
188 unpackData[i] = TextCoder::Instance().GetUCS2Value(currentValue);
189 }
190 }
191 return true;
192 }
193
charToBcd(const char c)194 uint8_t GsmSmsCommonUtils::charToBcd(const char c)
195 {
196 if (c == '*') {
197 return HEX_VALUE_0A;
198 } else if (c == '#') {
199 return HEX_VALUE_0B;
200 } else if (c == '+') {
201 return HEX_VALUE_FE;
202 } else {
203 return static_cast<uint8_t>(c - '0');
204 }
205 }
206
DigitToBcd(const char * digit,uint8_t digitLen,uint8_t * bcd,uint8_t bcdLen,uint8_t & len)207 bool GsmSmsCommonUtils::DigitToBcd(const char *digit, uint8_t digitLen, uint8_t *bcd, uint8_t bcdLen, uint8_t &len)
208 {
209 if (digit == nullptr || bcd == nullptr || len >= bcdLen) {
210 TELEPHONY_LOGE("data error.");
211 return false;
212 }
213 len = 0;
214 for (uint8_t i = 0; i < digitLen; i++) {
215 uint8_t temp = charToBcd(digit[i]);
216 if (temp != HEX_VALUE_FE) {
217 if (len >= bcdLen) {
218 TELEPHONY_LOGE("len invalid.");
219 return false;
220 }
221 if ((i % DIGITAL_STEP) == 0) {
222 bcd[len] = temp & HEX_VALUE_0F;
223 } else {
224 bcd[len++] |= ((temp & HEX_VALUE_0F) << HEX_VALUE_04);
225 }
226 }
227 }
228
229 if (len + 1 >= bcdLen) {
230 TELEPHONY_LOGE("len invalid.");
231 return false;
232 }
233 if ((digitLen % DIGITAL_STEP) == 1) {
234 bcd[len++] |= HEX_VALUE_F0;
235 }
236 return true;
237 }
238
BcdToDigit(const uint8_t * bcd,uint8_t bcdLen,std::string & digit,uint8_t maxDigitLen)239 bool GsmSmsCommonUtils::BcdToDigit(const uint8_t *bcd, uint8_t bcdLen, std::string &digit, uint8_t maxDigitLen)
240 {
241 if (bcd == nullptr || bcdLen == 0 || maxDigitLen == 0) {
242 TELEPHONY_LOGE("data error.");
243 return false;
244 }
245 for (uint8_t i = 0; i < bcdLen; i++) {
246 uint8_t temp = bcd[i] & HEX_VALUE_0F;
247 if (digit.size() + MIN_REMAIN_LEN >= maxDigitLen) {
248 TELEPHONY_LOGE("digit size over max");
249 return false;
250 }
251 digit.push_back(BcdToChar(temp));
252 temp = (bcd[i] & HEX_VALUE_F0) >> HEX_VALUE_04;
253 if (temp == HEX_VALUE_0F) {
254 return true;
255 }
256 digit.push_back(BcdToChar(temp));
257 }
258 return true;
259 }
260
BcdToChar(const uint8_t b)261 char GsmSmsCommonUtils::BcdToChar(const uint8_t b)
262 {
263 if (b == HEX_VALUE_0A) {
264 return '*';
265 } else if (b == HEX_VALUE_0B) {
266 return '#';
267 }
268 return static_cast<char>('0' + b);
269 }
270 } // namespace Telephony
271 } // namespace OHOS