1 /*
2 * Copyright (C) 2024 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 "asn1_utils.h"
17 #include <cctype>
18 #include <cstdio>
19 #include <securec.h>
20 #include <sstream>
21 #include "asn1_constants.h"
22 #include "telephony_errors.h"
23
24 namespace OHOS {
25 namespace Telephony {
26 namespace {
27 const uint32_t HEX_STR_MAX_LENGTH = 4;
28 const uint32_t HEX_DATA_LEN = 16;
29 const uint32_t OFFSET_ONE_BIT = 1;
30 const uint32_t OFFSET_TWO_BIT = 2;
31 const uint32_t OFFSET_FOUR_BIT = 4;
32 const uint32_t OFFSET_THREE_BYTE = 24;
33 const uint32_t ONE_BYTE_LENGTH = 1;
34 const uint32_t TWO_BYTE_LENGTH = 2;
35 const uint32_t THREE_BYTE_LENGTH = 3;
36 const uint32_t FOUR_BYTE_LENGTH = 4;
37 const uint8_t ZERO_VALUE_OCCPUPIED_BIT_COUNT = 8;
38 const uint32_t NONZERO_OCCUPIED_BITS = 7;
39 // For exchanging adjacent bit pairs
40 const uint32_t MASK_PAIRS = 0x55555555;
41 // For swap adjacent 4-bit blocks
42 const uint32_t MASK_NIBBLES = 0x33333333;
43 // For swap adjacent bytes
44 const uint32_t MASK_BYTES = 0x0f0f0f0f;
45 // For exchange high and low 16 bits
46 const uint32_t MASK_HALFWORDS = 0xff00;
47
48 const uint32_t MASK_BYTES_ONE_BYTE = 0x0F;
49 const uint32_t MASK_NIBBLES_ONE_BYTE = 0x33;
50 const uint32_t MASK_PAIRS_ONE_BYTE = 0x55;
51 }
52
IsConstructedTag(uint32_t tag)53 bool Asn1Utils::IsConstructedTag(uint32_t tag)
54 {
55 std::vector<uint8_t> tagBytes;
56 uint32_t bytesLen = UintToBytes(tag, tagBytes);
57 if (bytesLen == 0 || tagBytes.empty()) {
58 TELEPHONY_LOGE("failed to transform uint data to bytes.");
59 return false;
60 }
61 return (static_cast<uint8_t>(tagBytes[0]) & BIT6_MASK) != 0;
62 }
63
CalculateEncodedBytesNumForLength(uint32_t length)64 uint32_t Asn1Utils::CalculateEncodedBytesNumForLength(uint32_t length)
65 {
66 // default length is 1 byte
67 uint32_t len = 1;
68 if (length > MAX_INT8) {
69 len += ByteCountForUint(length);
70 }
71 return len;
72 }
73
ByteCountForUint(uint32_t value)74 uint32_t Asn1Utils::ByteCountForUint(uint32_t value)
75 {
76 return ByteCountForInt(value, false);
77 }
78
ByteCountForInt(uint32_t value,bool isSigned)79 uint32_t Asn1Utils::ByteCountForInt(uint32_t value, bool isSigned)
80 {
81 if (isSigned) {
82 if (value <= MAX_INT8) {
83 return ONE_BYTE_LENGTH;
84 }
85 if (value <= MAX_INT16) {
86 return TWO_BYTE_LENGTH;
87 }
88 if (value <= MAX_INT24) {
89 return THREE_BYTE_LENGTH;
90 }
91 } else {
92 if (value <= MAX_UINT8) {
93 return ONE_BYTE_LENGTH;
94 }
95 if (value <= MAX_UINT16) {
96 return TWO_BYTE_LENGTH;
97 }
98 if (value <= MAX_UINT24) {
99 return THREE_BYTE_LENGTH;
100 }
101 }
102 return FOUR_BYTE_LENGTH;
103 }
104
105 // convert bytes array to string
BchToString(const std::vector<uint8_t> & src,std::string & destStr)106 void Asn1Utils::BchToString(const std::vector<uint8_t> &src, std::string &destStr)
107 {
108 std::string hexStr = BytesToHexStr(src);
109 destStr = SwapHexCharPair(hexStr);
110 }
111
BcdToBytes(const std::string & bcd,std::vector<uint8_t> & bytes)112 void Asn1Utils::BcdToBytes(const std::string &bcd, std::vector<uint8_t> &bytes)
113 {
114 std::string hexStr = SwapHexCharPair(bcd);
115 bytes = HexStrToBytes(hexStr);
116 }
117
BytesToHexStr(const std::vector<uint8_t> & bytes)118 std::string Asn1Utils::BytesToHexStr(const std::vector<uint8_t> &bytes)
119 {
120 if (bytes.size() > MAX_BPP_LENGTH) {
121 TELEPHONY_LOGE("bytes length(%{public}lu) is more than max byte.", bytes.size());
122 return "";
123 }
124 std::ostringstream oss;
125 for (size_t i = 0; i < bytes.size(); i++) {
126 oss << std::hex << std::uppercase << std::setw(BYTE_TO_HEX_LEN) << std::setfill('0') << (bytes[i] & MAX_UINT8);
127 }
128 return oss.str();
129 }
130
ByteToHexStr(uint8_t src,std::string & dest)131 uint32_t Asn1Utils::ByteToHexStr(uint8_t src, std::string &dest)
132 {
133 std::ostringstream oss;
134 oss << std::hex << std::uppercase << std::setw(BYTE_TO_HEX_LEN) << std::setfill('0') << (src & MAX_UINT8);
135 dest = oss.str();
136 return static_cast<uint32_t>(dest.size());
137 }
138
HexStrToBytes(const std::string & hexStr)139 std::vector<uint8_t> Asn1Utils::HexStrToBytes(const std::string& hexStr)
140 {
141 std::vector<uint8_t> ret = {};
142 if (hexStr.length() > (MAX_BPP_LENGTH * BYTE_TO_HEX_LEN)) {
143 TELEPHONY_LOGE("hexStr length(%{public}lu) is more than max byte.", hexStr.length());
144 return ret;
145 }
146
147 if ((hexStr.length() % BYTE_TO_HEX_LEN) != 0) {
148 return ret;
149 }
150
151 for (size_t i = 0; i < hexStr.length(); i += BYTE_TO_HEX_LEN) {
152 uint8_t byte = static_cast<uint8_t>(strtol((hexStr.substr(i, BYTE_TO_HEX_LEN)).c_str(),
153 nullptr, HEX_DATA_LEN));
154 ret.push_back(byte);
155 }
156 return ret;
157 }
158
BytesToInt(const std::vector<uint8_t> & src,uint32_t offset,uint32_t length,int32_t & valInt)159 bool Asn1Utils::BytesToInt(const std::vector<uint8_t> &src, uint32_t offset, uint32_t length, int32_t &valInt)
160 {
161 if (length > HEX_STR_MAX_LENGTH || (offset + length) > src.size()) {
162 TELEPHONY_LOGE("length(%{public}d) or offset(%{public}d) is invalid.", length, offset);
163 return false;
164 }
165 std::vector<uint8_t> subByteStream(src.begin() + offset, src.begin() + offset + length);
166 std::string hexStr = BytesToHexStr(subByteStream);
167 valInt = static_cast<int32_t>(strtol(hexStr.c_str(), nullptr, HEX_DATA_LEN));
168 return true;
169 }
170
UintToBytes(const uint32_t value,std::vector<uint8_t> & bytes)171 uint32_t Asn1Utils::UintToBytes(const uint32_t value, std::vector<uint8_t> &bytes)
172 {
173 uint32_t len = ByteCountForInt(value, false);
174 std::ostringstream oss;
175 oss << std::hex << std::uppercase << std::setw(len * BYTE_TO_HEX_LEN) << std::setfill('0') << value;
176 std::string hexStr = oss.str();
177 bytes = HexStrToBytes(hexStr);
178 return len;
179 }
180
IntToBytes(int32_t value,std::vector<uint8_t> & dest)181 uint32_t Asn1Utils::IntToBytes(int32_t value, std::vector<uint8_t> &dest)
182 {
183 uint32_t len = ByteCountForInt(static_cast<uint32_t>(value), true);
184 std::ostringstream oss;
185 oss << std::hex << std::uppercase << std::setw(len * BYTE_TO_HEX_LEN) << std::setfill('0') << value;
186 std::string hexStr = oss.str();
187 dest = HexStrToBytes(hexStr);
188 return len;
189 }
190
BytesToString(const std::vector<uint8_t> & src)191 std::string Asn1Utils::BytesToString(const std::vector<uint8_t> &src)
192 {
193 std::string hexStr = BytesToHexStr(src);
194 std::string dest = HexStrToString(hexStr);
195 return dest;
196 }
197
StrToHexStr(const std::string & str)198 std::string Asn1Utils::StrToHexStr(const std::string& str)
199 {
200 std::string inputStr = str;
201 std::vector<uint8_t> bytes = {};
202 for (size_t i = 0; i < inputStr.length(); i++) {
203 bytes.push_back(static_cast<uint8_t>(inputStr[i]));
204 }
205 std::string result = BytesToHexStr(bytes);
206 return result;
207 }
208
HexStrToString(const std::string & hexStr)209 std::string Asn1Utils::HexStrToString(const std::string& hexStr)
210 {
211 std::string inputHexStr = hexStr;
212 std::vector<uint8_t> bytes = HexStrToBytes(inputHexStr);
213 std::string result("");
214 for (size_t i = 0; i < bytes.size(); i++) {
215 result += (static_cast<char>(bytes[i]));
216 }
217 return result;
218 }
219
StringToBytes(const std::string & src)220 std::vector<uint8_t> Asn1Utils::StringToBytes(const std::string &src)
221 {
222 std::string hexStr = StrToHexStr(src);
223 std::vector<uint8_t> dest = HexStrToBytes(hexStr);
224 return dest;
225 }
226
ReverseInt(uint32_t value)227 uint32_t Asn1Utils::ReverseInt(uint32_t value)
228 {
229 uint32_t valueTemp = value;
230 // Exchanging adjacent bit pairs
231 valueTemp = ((valueTemp & MASK_PAIRS) << OFFSET_ONE_BIT) | ((valueTemp >> OFFSET_ONE_BIT) & MASK_PAIRS);
232 // Swap adjacent 4-bit blocks
233 valueTemp = ((valueTemp & MASK_NIBBLES) << OFFSET_TWO_BIT) | ((valueTemp >> OFFSET_TWO_BIT) & MASK_NIBBLES);
234 // Swap adjacent bytes
235 valueTemp = ((valueTemp & MASK_BYTES) << OFFSET_FOUR_BIT) | ((valueTemp >> OFFSET_FOUR_BIT) & MASK_BYTES);
236 // Exchange high and low 16 bits
237 valueTemp = (valueTemp << OFFSET_THREE_BYTE) | ((valueTemp & MASK_HALFWORDS) << OFFSET_EIGHT_BIT) |
238 ((valueTemp >> OFFSET_EIGHT_BIT) & MASK_HALFWORDS) | (valueTemp >> OFFSET_THREE_BYTE);
239 return valueTemp;
240 }
241
CountTrailingZeros(const uint8_t value)242 uint8_t Asn1Utils::CountTrailingZeros(const uint8_t value)
243 {
244 if (value == 0) {
245 return ZERO_VALUE_OCCPUPIED_BIT_COUNT;
246 }
247
248 uint32_t valueTemp = ((static_cast<uint32_t>(value)) & MAX_UINT8);
249 // The number of bits occupied by non-zero values
250 uint8_t nonZeroBitCount = static_cast<uint8_t>(NONZERO_OCCUPIED_BITS);
251 if ((valueTemp & static_cast<uint32_t>(MASK_BYTES_ONE_BYTE)) != 0) {
252 nonZeroBitCount -= static_cast<uint8_t>(OFFSET_FOUR_BIT);
253 }
254 if ((valueTemp & static_cast<uint32_t>(MASK_NIBBLES_ONE_BYTE)) != 0) {
255 nonZeroBitCount -= static_cast<uint8_t>(OFFSET_TWO_BIT);
256 }
257 if ((valueTemp & static_cast<uint32_t>(MASK_PAIRS_ONE_BYTE)) != 0) {
258 nonZeroBitCount -= static_cast<uint8_t>(OFFSET_ONE_BIT);
259 }
260 return nonZeroBitCount;
261 }
262
263 // convert bytes array to string
SwapHexCharPair(const std::string & hexStr)264 std::string Asn1Utils::SwapHexCharPair(const std::string &hexStr)
265 {
266 std::string result = "";
267 if (hexStr.length() > (MAX_UINT8 * BYTE_TO_HEX_LEN)) {
268 return result;
269 }
270
271 std::string tmphexStr = hexStr;
272 if (tmphexStr.length() % BYTE_TO_HEX_LEN != 0) {
273 tmphexStr += "0";
274 }
275 for (size_t i = 0; i < tmphexStr.length(); i += BYTE_TO_HEX_LEN) {
276 result += tmphexStr.substr(i + ONE_BYTE_LENGTH, ONE_BYTE_LENGTH);
277 result += tmphexStr.substr(i, ONE_BYTE_LENGTH);
278 }
279 return result;
280 }
281 } // namespace Telephony
282 }
283