• 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     uint32_t byteLen = 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     if (constructed_) {
281         TELEPHONY_LOGE("Cannot get value of a constructed node.");
282         return TELEPHONY_ERR_ARGUMENT_INVALID;
283     }
284 
285     if (dataBytes_.empty()) {
286         TELEPHONY_LOGE("Data bytes cannot be nullptr.");
287         return TELEPHONY_ERR_ARGUMENT_INVALID;
288     }
289     return Asn1Utils::BytesToInt(dataBytes_, dataOffset_, dataLength_);
290 }
291 
Asn1AsString(std::string & output)292 uint32_t Asn1Node::Asn1AsString(std::string &output)
293 {
294     uint32_t hexStrLen = 0;
295     if (constructed_) {
296         TELEPHONY_LOGE("Cannot get value of a constructed node.");
297         return hexStrLen;
298     }
299 
300     if (dataBytes_.empty()) {
301         TELEPHONY_LOGE("Data bytes cannot be nullptr.");
302         return hexStrLen;
303     }
304     std::string hexStr = Asn1Utils::BytesToHexStr(dataBytes_);
305     output = hexStr;
306     return static_cast<uint32_t>(hexStr.length());
307 }
308 
Asn1AsBits()309 int32_t Asn1Node::Asn1AsBits()
310 {
311     int32_t integerVal = 0;
312     if (constructed_) {
313         TELEPHONY_LOGE("Cannot get value of a constructed node.");
314         return integerVal;
315     }
316 
317     if (dataBytes_.empty()) {
318         TELEPHONY_LOGE("Data bytes cannot be nullptr.");
319         return integerVal;
320     }
321 
322     if (dataLength_ > MAX_DATA_LENGTH || dataLength_ < MIN_DATA_LENGTH) {
323         TELEPHONY_LOGE("dataLength_ is invalid.");
324         return integerVal;
325     }
326 
327     uint32_t bits = 0;
328     bits = static_cast<uint32_t>(Asn1Utils::BytesToInt(dataBytes_, dataOffset_ + 1,
329         dataLength_ - 1));
330     int32_t index = static_cast<int32_t>(dataLength_) - 1;
331     for (index; index < sizeof(int32_t); index++) {
332         bits <<= OFFSET_EIGHT_BIT;
333     }
334     integerVal = static_cast<int32_t>(Asn1Utils::ReverseInt(bits));
335     return integerVal;
336 }
337 } // namespace Telephony
338 }