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) {
110 TELEPHONY_LOGE("data error.");
111 return false;
112 }
113 if (shift > 0) {
114 buffer.MoveForward(1);
115 }
116
117 for (; dstIdx < dataLen; dstIdx++) {
118 if (shift == 0) {
119 uint8_t oneByte = 0;
120 if (!buffer.ReadByte(oneByte)) {
121 TELEPHONY_LOGE("get data error.");
122 return false;
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 if (shift > 0) {
132 uint8_t oneByte = 0;
133 if (!buffer.PickOneByteFromIndex(buffer.GetIndex() - 1, oneByte)) {
134 TELEPHONY_LOGE("get data error.");
135 return false;
136 }
137 uint8_t nextByte = 0;
138 if (!buffer.PickOneByte(nextByte)) {
139 TELEPHONY_LOGE("get data error.");
140 return false;
141 }
142
143 unpackData[dstIdx] = (oneByte >> shift) + (nextByte << (SMS_BYTE_BIT - shift));
144 unpackData[dstIdx] &= HEX_VALUE_7F;
145 shift--;
146 if (shift > 0) {
147 buffer.MoveForward(1);
148 }
149 }
150 }
151 return true;
152 }
153
DigitToBcd(const char * digit,uint8_t digitLen,uint8_t * bcd,uint8_t bcdLen,uint8_t & len)154 bool GsmSmsCommonUtils::DigitToBcd(const char *digit, uint8_t digitLen, uint8_t *bcd, uint8_t bcdLen, uint8_t &len)
155 {
156 if (digit == nullptr || bcd == nullptr || len >= bcdLen) {
157 TELEPHONY_LOGE("data error.");
158 return false;
159 }
160
161 len = 0;
162 uint8_t temp;
163 for (uint8_t i = 0; i < digitLen; i++) {
164 switch (digit[i]) {
165 case '*':
166 temp = HEX_VALUE_0A;
167 break;
168 case '#':
169 temp = HEX_VALUE_0B;
170 break;
171 case 'P':
172 case 'p':
173 temp = HEX_VALUE_0C;
174 break;
175 default:
176 temp = digit[i] - '0';
177 break;
178 }
179
180 if (len >= bcdLen) {
181 TELEPHONY_LOGE("len invalid.");
182 return false;
183 }
184 if ((i % DIGITAL_STEP) == 0) {
185 bcd[len] = temp & HEX_VALUE_0F;
186 } else {
187 bcd[len++] |= ((temp & HEX_VALUE_0F) << HEX_VALUE_04);
188 }
189 }
190
191 if (len + 1 >= bcdLen) {
192 TELEPHONY_LOGE("len invalid.");
193 return false;
194 }
195 if ((digitLen % DIGITAL_STEP) == 1) {
196 bcd[len++] |= HEX_VALUE_F0;
197 }
198 return true;
199 }
200
BcdToDigit(const uint8_t * bcd,uint8_t bcdLen,std::string & digit,uint8_t maxDigitLen)201 bool GsmSmsCommonUtils::BcdToDigit(const uint8_t *bcd, uint8_t bcdLen, std::string &digit, uint8_t maxDigitLen)
202 {
203 if (bcd == nullptr || bcdLen == 0 || maxDigitLen == 0) {
204 TELEPHONY_LOGE("data error.");
205 return false;
206 }
207
208 uint8_t temp;
209 for (uint8_t i = 0; i < bcdLen; i++) {
210 temp = bcd[i] & HEX_VALUE_0F;
211 if (digit.size() + MIN_REMAIN_LEN >= maxDigitLen) {
212 TELEPHONY_LOGE("digit size over max");
213 return false;
214 }
215 digit.push_back(BcdToChar(temp));
216 temp = (bcd[i] & HEX_VALUE_F0) >> HEX_VALUE_04;
217 if (temp == HEX_VALUE_0F) {
218 return true;
219 }
220 digit.push_back(BcdToChar(temp));
221 }
222 return true;
223 }
224
BcdToChar(const uint8_t c)225 char GsmSmsCommonUtils::BcdToChar(const uint8_t c)
226 {
227 char temp = 0;
228 switch (c) {
229 case HEX_VALUE_0A:
230 temp = '*';
231 break;
232 case HEX_VALUE_0B:
233 temp = '#';
234 break;
235 case HEX_VALUE_0C:
236 temp = 'P';
237 break;
238 default:
239 temp = c + '0';
240 break;
241 }
242 return temp;
243 }
244 } // namespace Telephony
245 } // namespace OHOS