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