• 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) {
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