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_node.h"
17
18 #include <cctype>
19 #include <cstdio>
20 #include <securec.h>
21 #include "asn1_constants.h"
22 #include "asn1_decoder.h"
23 #include "asn1_utils.h"
24 #include "telephony_errors.h"
25
26 namespace OHOS {
27 namespace Telephony {
28 namespace {
29 const uint32_t MAX_DATA_LENGTH = 4;
30 const uint32_t MIN_DATA_LENGTH = 1;
31 }
32
Asn1Node(const uint32_t tag,const std::vector<uint8_t> & src,uint32_t offset,uint32_t length)33 Asn1Node::Asn1Node(const uint32_t tag, const std::vector<uint8_t> &src, uint32_t offset, uint32_t length)
34 {
35 TELEPHONY_LOGD("enter InitAsn1Node %{public}u", tag);
36 tag_ = tag;
37 constructed_ = Asn1Utils::IsConstructedTag(tag);
38 dataBytes_ = src;
39 dataOffset_ = offset;
40 dataLength_ = length;
41 encodedLength_ = Asn1Utils::ByteCountForUint(tag) + Asn1Utils::CalculateEncodedBytesNumForLength(length) + length;
42 }
43
Asn1NodeToHexStr(std::string & destStr)44 uint32_t Asn1Node::Asn1NodeToHexStr(std::string &destStr)
45 {
46 TELEPHONY_LOGD("enter Asn1NodeToHexStr");
47 std::vector<uint8_t> byteStream;
48 Asn1NodeToBytes(byteStream);
49 destStr = Asn1Utils::BytesToHexStr(byteStream);
50 return static_cast<uint32_t>(destStr.length());
51 }
52
Asn1NodeToBytes(std::vector<uint8_t> & byteStream)53 uint32_t Asn1Node::Asn1NodeToBytes(std::vector<uint8_t> &byteStream)
54 {
55 uint32_t byteLen = 0;
56 if (encodedLength_ == 0) {
57 TELEPHONY_LOGE("encoded length is 0");
58 return byteLen;
59 }
60 Asn1Write(byteStream);
61 return static_cast<uint32_t>(byteStream.size());
62 }
63
Asn1Write(std::vector<uint8_t> & dest)64 void Asn1Node::Asn1Write(std::vector<uint8_t> &dest)
65 {
66 // Write the tag.
67 TELEPHONY_LOGD("enter Asn1Write tag:%{public}x", tag_);
68 std::vector<uint8_t> uintByte;
69 uint32_t bytesLen = Asn1Utils::UintToBytes(tag_, uintByte);
70 if (bytesLen == 0 || uintByte.empty()) {
71 TELEPHONY_LOGE("failed to transform uint data to bytes.");
72 return;
73 }
74 dest.insert(dest.end(), uintByte.begin(), uintByte.end());
75
76 // Write the length.
77 if (dataLength_ <= MAX_INT8) {
78 dest.push_back(static_cast<char>(dataLength_));
79 TELEPHONY_LOGD("dataLength_: %{public}u, length's length:0", dataLength_);
80 } else {
81 // Bytes required for encoding the length
82 uint8_t encodeLens = static_cast<uint8_t>(Asn1Utils::ByteCountForUint(dataLength_) | BIT8_MASK);
83 dest.push_back(static_cast<char>(encodeLens));
84 std::vector<uint8_t> uintByteStr;
85 bytesLen = Asn1Utils::UintToBytes(dataLength_, uintByteStr);
86 if (bytesLen == 0 || uintByteStr.empty()) {
87 TELEPHONY_LOGE("failed to transform uint data to bytes.");
88 return;
89 }
90 dest.insert(dest.end(), uintByteStr.begin(), uintByteStr.end());
91 TELEPHONY_LOGD("dataLength_: %{public}u, length's length:%{public}d", dataLength_, bytesLen);
92 }
93
94 // Write the data.
95 std::lock_guard<std::mutex> lock(mutex_);
96 if (constructed_ && dataBytes_.empty()) {
97 std::shared_ptr<Asn1Node> asn1Node = nullptr;
98 for (auto it = children_.begin(); it != children_.end(); ++it) {
99 asn1Node = *it;
100 if (asn1Node == nullptr) {
101 break;
102 }
103 asn1Node->Asn1Write(dest);
104 }
105 } else if (!dataBytes_.empty()) {
106 TELEPHONY_LOGD("dataLen: %{public}u", dataLength_);
107 dest.insert(dest.end(), dataBytes_.begin(), dataBytes_.end());
108 }
109 }
110
Asn1GetChild(const uint32_t tag)111 std::shared_ptr<Asn1Node> Asn1Node::Asn1GetChild(const uint32_t tag)
112 {
113 if (!constructed_) {
114 TELEPHONY_LOGE("TAG not found tag = %{public}u.", tag);
115 return nullptr;
116 }
117 if (Asn1BuildChildren() != TELEPHONY_ERR_SUCCESS) {
118 TELEPHONY_LOGE("build children err.");
119 return nullptr;
120 }
121 std::shared_ptr<Asn1Node> curNode = nullptr;
122 std::lock_guard<std::mutex> lock(mutex_);
123 for (auto it = children_.begin(); it != children_.end(); ++it) {
124 curNode = *it;
125 if (curNode == nullptr) {
126 break;
127 }
128 if (curNode->GetNodeTag() == tag) {
129 return curNode;
130 }
131 }
132 return nullptr;
133 }
134
Asn1HasChild(const uint32_t tag)135 bool Asn1Node::Asn1HasChild(const uint32_t tag)
136 {
137 return (Asn1GetChild(tag) != nullptr);
138 }
139
Asn1GetGrandson(const uint32_t firstLevelTag,const uint32_t secondLevelTag)140 std::shared_ptr<Asn1Node> Asn1Node::Asn1GetGrandson(const uint32_t firstLevelTag, const uint32_t secondLevelTag)
141 {
142 std::shared_ptr<Asn1Node> resultNode = nullptr;
143 resultNode = Asn1GetChild(firstLevelTag);
144 if (resultNode == nullptr) {
145 return nullptr;
146 }
147 resultNode = resultNode->Asn1GetChild(secondLevelTag);
148 return resultNode;
149 }
150
Asn1GetGreatGrandson(const uint32_t firstLevelTag,const uint32_t secondLevelTag,const uint32_t thirdLevelTag)151 std::shared_ptr<Asn1Node> Asn1Node::Asn1GetGreatGrandson(const uint32_t firstLevelTag, const uint32_t secondLevelTag,
152 const uint32_t thirdLevelTag)
153 {
154 std::shared_ptr<Asn1Node> resultNode = nullptr;
155 resultNode = Asn1GetGrandson(firstLevelTag, secondLevelTag);
156 if (resultNode == nullptr) {
157 return nullptr;
158 }
159 resultNode = resultNode->Asn1GetChild(thirdLevelTag);
160 return resultNode;
161 }
162
Asn1GetChildren(const uint32_t tag,std::list<std::shared_ptr<Asn1Node>> & children)163 int32_t Asn1Node::Asn1GetChildren(const uint32_t tag, std::list<std::shared_ptr<Asn1Node>> &children)
164 {
165 TELEPHONY_LOGD("enter Asn1GetChildren");
166 if (!constructed_) {
167 TELEPHONY_LOGE("TAG not found tag = %{public}u.", tag);
168 return TELEPHONY_ERR_SUCCESS;
169 }
170 if (Asn1BuildChildren() != TELEPHONY_ERR_SUCCESS) {
171 TELEPHONY_LOGE("children is null");
172 return TELEPHONY_ERR_FAIL;
173 }
174 std::shared_ptr<Asn1Node> curNode = nullptr;
175 std::lock_guard<std::mutex> lock(mutex_);
176 for (auto it = children_.begin(); it != children_.end(); ++it) {
177 curNode = *it;
178 if (curNode == nullptr) {
179 break;
180 }
181 if (curNode->GetNodeTag() == tag) {
182 children.push_back(curNode);
183 }
184 }
185 return TELEPHONY_ERR_SUCCESS;
186 }
187
Asn1BuildChildren()188 int32_t Asn1Node::Asn1BuildChildren()
189 {
190 if (!constructed_) {
191 TELEPHONY_LOGE("TAG not constructed = %{public}d.", constructed_);
192 return TELEPHONY_ERR_FAIL;
193 }
194
195 std::lock_guard<std::mutex> lock(mutex_);
196 if (children_.empty()) {
197 TELEPHONY_LOGD("children is empty");
198 }
199
200 if (!dataBytes_.empty()) {
201 Asn1Decoder decoder(dataBytes_, dataOffset_, dataLength_ - dataOffset_);
202 while (decoder.Asn1HasNextNode()) {
203 auto subNode = decoder.Asn1NextNode();
204 if (subNode == nullptr) {
205 break;
206 }
207 children_.push_back(std::move(subNode));
208 }
209
210 dataBytes_.clear();
211 dataOffset_ = 0;
212 }
213 return TELEPHONY_ERR_SUCCESS;
214 }
215
Asn1GetHeadAsHexStr(std::string & headHex)216 uint32_t Asn1Node::Asn1GetHeadAsHexStr(std::string &headHex)
217 {
218 std::string cursor = "";
219 uint32_t cursorLen = 0;
220 // get tag
221 std::vector<uint8_t> byteStream;
222 uint32_t byteLen = Asn1Utils::UintToBytes(tag_, byteStream);
223 if (byteLen == 0 || byteStream.empty()) {
224 TELEPHONY_LOGE("failed to transform uint data to bytes.");
225 return TELEPHONY_ERR_FAIL;
226 }
227 cursor += Asn1Utils::BytesToHexStr(byteStream);
228 cursorLen += static_cast<uint32_t>(cursor.length());
229
230 std::string hexStr = "";
231 std::string curHexStr = "";
232 // get length
233 if (dataLength_ <= MAX_INT8) {
234 cursorLen += Asn1Utils::ByteToHexStr(static_cast<uint8_t>(dataLength_), hexStr);
235 } else {
236 uint32_t bytesCount = Asn1Utils::ByteCountForUint(dataLength_);
237 cursorLen += Asn1Utils::ByteToHexStr(static_cast<uint8_t>(bytesCount | BIT8_MASK), hexStr);
238
239 std::vector<uint8_t> dataLenStream;
240 byteLen = Asn1Utils::UintToBytes(dataLength_, dataLenStream);
241 if (byteLen == 0 || dataLenStream.empty()) {
242 TELEPHONY_LOGE("failed to transform uint data to bytes.");
243 return TELEPHONY_ERR_FAIL;
244 }
245 curHexStr = Asn1Utils::BytesToHexStr(dataLenStream);
246 cursorLen += static_cast<uint32_t>(curHexStr.length());
247 }
248 cursor += hexStr;
249 cursor += curHexStr;
250 headHex = cursor;
251 return cursorLen;
252 }
253
Asn1AsBytes(std::vector<uint8_t> & output)254 uint32_t Asn1Node::Asn1AsBytes(std::vector<uint8_t> &output)
255 {
256 uint32_t dataLen = 0;
257 if (constructed_) {
258 TELEPHONY_LOGE("Cannot get value of a constructed node.");
259 return dataLen;
260 }
261
262 if (dataBytes_.empty()) {
263 TELEPHONY_LOGE("Data bytes cannot be nullptr.");
264 return dataLen;
265 }
266
267 std::vector<uint8_t> dataBytes = dataBytes_;
268 if ((dataLength_ - dataOffset_) > dataBytes.size()) {
269 TELEPHONY_LOGE("dataOffset_ is out of string range.");
270 return dataLen;
271 }
272 std::vector<uint8_t> byteSteamSegment(dataBytes.begin() + dataOffset_, dataBytes.begin() + dataLength_);
273 output = byteSteamSegment;
274 dataLen = dataLength_ - dataOffset_;
275 return dataLen;
276 }
277
Asn1AsInteger()278 int32_t Asn1Node::Asn1AsInteger()
279 {
280 int32_t dataLen = -1;
281 if (constructed_) {
282 TELEPHONY_LOGE("Cannot get value of a constructed node.");
283 return dataLen;
284 }
285
286 if (dataBytes_.empty()) {
287 TELEPHONY_LOGE("Data bytes cannot be nullptr.");
288 return dataLen;
289 }
290
291 Asn1Utils::BytesToInt(dataBytes_, dataOffset_, dataLength_, dataLen);
292 return dataLen;
293 }
294
Asn1AsString(std::string & output)295 uint32_t Asn1Node::Asn1AsString(std::string &output)
296 {
297 uint32_t hexStrLen = 0;
298 if (constructed_) {
299 TELEPHONY_LOGE("Cannot get value of a constructed node.");
300 return hexStrLen;
301 }
302
303 if (dataBytes_.empty()) {
304 TELEPHONY_LOGE("Data bytes cannot be nullptr.");
305 return hexStrLen;
306 }
307 std::string hexStr = Asn1Utils::BytesToHexStr(dataBytes_);
308 output = hexStr;
309 return static_cast<uint32_t>(hexStr.length());
310 }
311
Asn1AsBits()312 int32_t Asn1Node::Asn1AsBits()
313 {
314 int32_t integerVal = 0;
315 if (constructed_) {
316 TELEPHONY_LOGE("Cannot get value of a constructed node.");
317 return integerVal;
318 }
319
320 if (dataBytes_.empty()) {
321 TELEPHONY_LOGE("Data bytes cannot be nullptr.");
322 return integerVal;
323 }
324
325 if (dataLength_ > MAX_DATA_LENGTH || dataLength_ < MIN_DATA_LENGTH) {
326 TELEPHONY_LOGE("dataLength_ is invalid.");
327 return integerVal;
328 }
329
330 int32_t dataBits = 0;
331 if (!Asn1Utils::BytesToInt(dataBytes_, dataOffset_ + 1, dataLength_ - 1, dataBits)) {
332 return integerVal;
333 }
334 uint32_t bits = static_cast<uint32_t>(dataBits);
335 for (int32_t i = static_cast<int32_t>(dataLength_) - 1; i < static_cast<int32_t>(sizeof(int32_t)); i++) {
336 bits <<= OFFSET_EIGHT_BIT;
337 }
338 integerVal = static_cast<int32_t>(Asn1Utils::ReverseInt(bits));
339 return integerVal;
340 }
341 } // namespace Telephony
342 }