1 /*
2  * Copyright (C) 2021 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 "icc_operator_rule.h"
17 
18 #include <algorithm>
19 #include <charconv>
20 #include <system_error>
21 
22 #include "telephony_log_wrapper.h"
23 
24 
25 namespace OHOS {
26 namespace Telephony {
27 constexpr int32_t INT32_INITVALUE = 0;
readOneByte(std::string::const_iterator & it,const std::string::const_iterator & ed,int32_t & res)28 static bool readOneByte(std::string::const_iterator &it, const std::string::const_iterator &ed, int32_t &res)
29 {
30     if (it == ed) {
31         TELEPHONY_LOGE("can not readTLVLength for empty string!!' ");
32         return false;
33     }
34     ++it;
35     if (it == ed) {
36         TELEPHONY_LOGE("can not readTLVLength for string length less 2");
37         return false;
38     }
39     const auto [nextPtr, err] =
40         std::from_chars(std::addressof(*(it - 1)), std::addressof(*(it + 1)), res, IccOperatorRule::HEX_);
41     if (err != std::errc()) {
42         const auto cond = std::make_error_condition(err);
43         TELEPHONY_LOGE("readLength occurent error!! '%{public}s' ", cond.message().data());
44         return false;
45     }
46     ++it;
47     return true;
48 }
49 
parseSimpleTLV(std::string::const_iterator & it,const std::string::const_iterator & ed,std::string & tagName,int32_t & len,std::string & value)50 static bool parseSimpleTLV(std::string::const_iterator &it, const std::string::const_iterator &ed,
51     std::string &tagName, int32_t &len, std::string &value)
52 {
53     size_t inputSize = static_cast<long unsigned int>(std::distance(it, ed));
54     if (inputSize < IccOperatorRule::TLV_STAG_CHARLEN) {
55         std::string temp(it, ed);
56         TELEPHONY_LOGE("parseSimpleTLV from '%{public}s' size:%{public}zu < %{public}d", temp.data(), inputSize,
57             IccOperatorRule::TLV_STAG_CHARLEN);
58         return false;
59     }
60     /* begin parse tagName */
61     tagName.clear();
62     std::copy_n(it, IccOperatorRule::TLV_STAG_CHARLEN, std::back_inserter(tagName));
63     TELEPHONY_LOGI("parseSimpleTLV read tagName: '%{public}s' ", tagName.data());
64     it += IccOperatorRule::TLV_STAG_CHARLEN;
65     /* begin parse length */
66     len = INT32_INITVALUE;
67     if (inputSize < IccOperatorRule::TLV_STAG_CHARLEN + IccOperatorRule::TLV_LEN_CHARLEN) {
68         std::string temp(it, ed);
69         TELEPHONY_LOGE("parseSimpleTLV from '%{public}s' size:%{public}zu < %{public}d", temp.data(), inputSize,
70             IccOperatorRule::TLV_STAG_CHARLEN + IccOperatorRule::TLV_LEN_CHARLEN);
71         return false;
72     }
73     if (!readOneByte(it, ed, len)) {
74         TELEPHONY_LOGE("parseSimpleTLV parse length fail!");
75         return false;
76     }
77     /* begin parse value */
78     value.clear();
79     const auto valueCharLen = len + len;
80     if (static_cast<int>(inputSize) <
81         IccOperatorRule::TLV_STAG_CHARLEN + IccOperatorRule::TLV_LEN_CHARLEN + valueCharLen) {
82         std::string temp(it, ed);
83         TELEPHONY_LOGE("parseSimpleTLV from '%{public}s' size:%{public}zu < %{public}d", temp.data(), inputSize,
84             IccOperatorRule::TLV_STAG_CHARLEN + IccOperatorRule::TLV_LEN_CHARLEN + valueCharLen);
85         return false;
86     }
87     std::copy_n(it, valueCharLen, std::back_inserter(value));
88     it += valueCharLen;
89     return true;
90 }
91 
CreateFromTLV(const std::string & hexStr,std::vector<IccOperatorRule> & result)92 bool IccOperatorRule::CreateFromTLV(const std::string &hexStr, std::vector<IccOperatorRule> &result)
93 {
94     TELEPHONY_LOGI("IccOperatorRule::CreateFromTLV  by hexStr Begin!");
95     return CreateFromTLV(hexStr.begin(), hexStr.end(), result);
96 }
97 
CreateFromTLV(const std::string::const_iterator & hexStrBeg,const std::string::const_iterator & hexStrEnd,std::vector<IccOperatorRule> & result)98 bool IccOperatorRule::CreateFromTLV(const std::string::const_iterator &hexStrBeg,
99     const std::string::const_iterator &hexStrEnd, std::vector<IccOperatorRule> &result)
100 {
101     TELEPHONY_LOGD("IccOperatorRule::CreateFromTLV by iterator Begin!");
102     result.clear();
103     const auto &[hexStrIt, prefixIt] =
104         std::mismatch(hexStrBeg, hexStrEnd, TAG_ALL_RULE.begin(), TAG_ALL_RULE.end());
105     // when TAG_ALL_RULE not a prefix of hexStrBeg
106     if (prefixIt != TAG_ALL_RULE.end()) {
107         std::string temp(hexStrBeg, hexStrEnd);
108         TELEPHONY_LOGE("hexStr:[%{public}s] not strartWith '%{public}s' !", temp.data(), TAG_ALL_RULE.data());
109         return false;
110     }
111     TELEPHONY_LOGI("start parse after of tag:'%{public}s'  !", TAG_ALL_RULE.data());
112     std::string::const_iterator strIt = hexStrBeg + TAG_ALL_RULE.size();
113     int32_t len = INT32_INITVALUE;
114     if (!readOneByte(strIt, hexStrEnd, len)) {
115         TELEPHONY_LOGE("after tagStr '%{public}s' had not LenStr !", TAG_ALL_RULE.data());
116         return false;
117     }
118     TELEPHONY_LOGI("read TAG_ALL_RULE len:%{public}d ", len);
119     IccOperatorRule rule;
120     int32_t totalLen = INT32_INITVALUE;
121     while (strIt != hexStrEnd && totalLen < len) {
122         int32_t ruleLen = INT32_INITVALUE;
123         if (!DecodeTLVTagRule(strIt, hexStrEnd, rule, ruleLen)) {
124             break;
125         }
126         totalLen += ruleLen;
127         TELEPHONY_LOGI("DecodeRule once count:%{public}d ,TAG_ALL_RULE len:%{public}d", totalLen, len);
128         result.push_back(rule);
129     }
130     TELEPHONY_LOGI("End parse element of Rule! Size:[%{public}zu]", result.size());
131     return true;
132 }
133 
DecodeTLVTagCertPkg(std::string::const_iterator & hexStrBeg,const std::string::const_iterator & hexStrEnd,IccOperatorRule & result)134 bool IccOperatorRule::DecodeTLVTagCertPkg(
135     std::string::const_iterator &hexStrBeg, const std::string::const_iterator &hexStrEnd, IccOperatorRule &result)
136 {
137     TELEPHONY_LOGI("Start parse TAG_CERT_PKG(%{public}s) for [%{public}s]", TAG_CERT_PKG.data(),
138         std::string(hexStrBeg, hexStrEnd).data());
139     const auto [hexStrIt, prefixIt] = std::mismatch(hexStrBeg, hexStrEnd, TAG_CERT_PKG.begin(), TAG_CERT_PKG.end());
140     if (prefixIt != TAG_CERT_PKG.end()) {
141         std::string temp(hexStrBeg, hexStrEnd);
142         TELEPHONY_LOGE("hexStr:[%{public}s] not strartWith '%{public}s' !", temp.data(), TAG_CERT_PKG.data());
143         return false;
144     }
145     hexStrBeg += TAG_CERT_PKG.size();
146     int32_t refDoLen = INT32_INITVALUE;
147     if (!readOneByte(hexStrBeg, hexStrEnd, refDoLen)) {
148         TELEPHONY_LOGE("after tagStr '%{public}s' had not LenStr !", TAG_CERT_PKG.data());
149         return false;
150     }
151     bool hasCertificate = false;
152     int32_t totalLen = INT32_INITVALUE;
153     while (hexStrBeg != hexStrEnd && totalLen < refDoLen) {
154         std::string tagName;
155         int32_t length = INT32_INITVALUE;
156         std::string value;
157         if (!parseSimpleTLV(hexStrBeg, hexStrEnd, tagName, length, value)) {
158             std::string temp(hexStrBeg, hexStrEnd);
159             TELEPHONY_LOGE("can not parse simple TLV at : '%{public}s'", temp.data());
160             return false;
161         }
162         totalLen += length + TLV_SIMPLE_TAG_ONEBYTE_LEN + TLV_SIMPLE_TAG_LENGTH_LEN;
163         TELEPHONY_LOGI("parse more TLV count:%{public}d , refDoLen:%{public}d", totalLen, refDoLen);
164         if (tagName == TAG_CERTIFICATE) {
165             result.SetCertificate(std::move(value));
166             hasCertificate = true;
167         } else if (tagName == TAG_PACKAGE) {
168             if (!result.SetPackageNameByHexStr(value)) {
169                 return false;
170             }
171         }
172     }
173     return hasCertificate;
174 }
175 
DecodeTLVTagLimits(std::string::const_iterator & hexStrBeg,const std::string::const_iterator & hexStrEnd,IccOperatorRule & result)176 bool IccOperatorRule::DecodeTLVTagLimits(
177     std::string::const_iterator &hexStrBeg, const std::string::const_iterator &hexStrEnd, IccOperatorRule &result)
178 {
179     TELEPHONY_LOGI("Start parse TAG_LIMITS(%{public}s) for [%{public}s]", TAG_LIMITS.data(),
180         std::string(hexStrBeg, hexStrEnd).data());
181     const auto [hexStrIt, prefixIt] = std::mismatch(hexStrBeg, hexStrEnd, TAG_LIMITS.begin(), TAG_LIMITS.end());
182     if (prefixIt != TAG_LIMITS.end()) {
183         std::string temp(hexStrBeg, hexStrEnd);
184         TELEPHONY_LOGE("hexStr:[%{public}s] not strartWith '%{public}s' !", temp.data(), TAG_LIMITS.data());
185         return false;
186     }
187     hexStrBeg += TAG_LIMITS.size();
188     int32_t arDoLen = INT32_INITVALUE;
189     if (!readOneByte(hexStrBeg, hexStrEnd, arDoLen)) {
190         TELEPHONY_LOGE("after tagStr '%{public}s' had not LenStr !", TAG_LIMITS.data());
191         return false;
192     }
193     int32_t totalLen = INT32_INITVALUE;
194     bool isReadTagPermArDo = false;
195     while (hexStrBeg != hexStrEnd && totalLen < arDoLen) {
196         std::string tagName;
197         int32_t length = INT32_INITVALUE;
198         std::string value;
199         if (!parseSimpleTLV(hexStrBeg, hexStrEnd, tagName, length, value)) {
200             std::string temp(hexStrBeg, hexStrEnd);
201             TELEPHONY_LOGE("can not parse simple TLV at : '%{public}s'", temp.data());
202             return false;
203         }
204         totalLen += length + TLV_SIMPLE_TAG_ONEBYTE_LEN + TLV_SIMPLE_TAG_LENGTH_LEN;
205         TELEPHONY_LOGI("parse more TLV count:%{public}d , arDolen:%{public}d", totalLen, arDoLen);
206         if (tagName == TAG_LIMIT) {
207             result.SetAccessLimit(std::move(value));
208             isReadTagPermArDo = true;
209         }
210     }
211     return isReadTagPermArDo;
212 }
213 
DecodeTLVTagRule(std::string::const_iterator & hexStrBeg,const std::string::const_iterator & hexStrEnd,IccOperatorRule & result,int32_t & len)214 bool IccOperatorRule::DecodeTLVTagRule(std::string::const_iterator &hexStrBeg,
215     const std::string::const_iterator &hexStrEnd, IccOperatorRule &result, int32_t &len)
216 {
217     TELEPHONY_LOGI(
218         "Start parse TAG_RULE(%{public}s) for [%{public}s]", TAG_RULE.data(), std::string(hexStrBeg, hexStrEnd).data());
219     len = INT32_INITVALUE;
220     const auto [hexStrIt, prefixIt] =
221         std::mismatch(hexStrBeg, hexStrEnd, TAG_RULE.begin(), TAG_RULE.end());
222     if (prefixIt != TAG_RULE.end()) {
223         TELEPHONY_LOGE("hexStr not strartWith '%{public}s' !", TAG_RULE.data());
224         return false;
225     }
226     len += TLV_SIMPLE_TAG_ONEBYTE_LEN;
227     hexStrBeg += TAG_RULE.size();
228     int32_t refArLen = INT32_INITVALUE;
229     if (!readOneByte(hexStrBeg, hexStrEnd, refArLen)) {
230         TELEPHONY_LOGE("after tagStr '%{public}s' had not LenStr !", TAG_RULE.data());
231         return false;
232     }
233     len += TLV_SIMPLE_TAG_LENGTH_LEN + refArLen;
234     if (!DecodeTLVTagCertPkg(hexStrBeg, hexStrEnd, result)) {
235         TELEPHONY_LOGE("DecodeTLVTagCertPkg fail !");
236         return false;
237     }
238     if (!DecodeTLVTagLimits(hexStrBeg, hexStrEnd, result)) {
239         TELEPHONY_LOGE("DecodeTLVTagLimits fail !");
240         return false;
241     }
242     return true;
243 }
244 
IccOperatorRule()245 IccOperatorRule::IccOperatorRule() {}
~IccOperatorRule()246 IccOperatorRule::~IccOperatorRule() {}
247 
GetPackageName(std::string & result) const248 void IccOperatorRule::GetPackageName(std::string &result) const
249 {
250     result.clear();
251     result = std::string(packageName_.begin(), packageName_.end());
252 }
253 
SetPackageName(const std::string & packageName)254 void IccOperatorRule::SetPackageName(const std::string &packageName)
255 {
256     this->packageName_ = packageName;
257 }
258 
SetPackageName(std::string && packageName)259 void IccOperatorRule::SetPackageName(std::string &&packageName)
260 {
261     this->packageName_.swap(packageName);
262 }
263 
SetPackageNameByHexStr(const std::string & hexStr)264 bool IccOperatorRule::SetPackageNameByHexStr(const std::string &hexStr)
265 {
266     packageName_.clear();
267     auto it = hexStr.begin();
268     while (it != hexStr.end()) {
269         int32_t value = INT32_INITVALUE;
270         if (!readOneByte(it, hexStr.end(), value)) {
271             TELEPHONY_LOGE("IccOperatorRule::SetPackageNameByHexStr fail !");
272             return false;
273         }
274         this->packageName_.push_back(static_cast<char>(value));
275     }
276     return true;
277 }
278 
GetCertificate(std::string & result) const279 void IccOperatorRule::GetCertificate(std::string &result) const
280 {
281     result.clear();
282     result = std::string(certificate_.begin(), certificate_.end());
283 }
284 
SetCertificate(const std::string & certificate)285 void IccOperatorRule::SetCertificate(const std::string &certificate)
286 {
287     this->certificate_ = certificate;
288 }
289 
SetCertificate(std::string && certificate)290 void IccOperatorRule::SetCertificate(std::string &&certificate)
291 {
292     this->certificate_.swap(certificate);
293 }
294 
SetAccessLimit(const std::string & accessLimit)295 void IccOperatorRule::SetAccessLimit(const std::string &accessLimit)
296 {
297     this->accessLimit_ = accessLimit;
298 }
299 
SetAccessLimit(std::string && accessLimit)300 void IccOperatorRule::SetAccessLimit(std::string &&accessLimit)
301 {
302     this->accessLimit_.swap(accessLimit);
303 }
304 
Matche(const std::string_view & certHash,const std::string_view & packageName) const305 bool IccOperatorRule::Matche(const std::string_view &certHash, const std::string_view &packageName) const
306 {
307     bool res = (this->certificate_ == certHash);
308     if (this->packageName_.empty()) {
309         return res;
310     }
311     return res && (this->packageName_ == packageName);
312 }
313 } // namespace Telephony
314 } // namespace OHOS
315