• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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