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