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 #include "ndef_wifi_data_parser.h"
16
17 #include "loghelper.h"
18 #include "ndef_message.h"
19 #include "nfc_sdk_common.h"
20
21 namespace OHOS {
22 namespace NFC {
23 namespace TAG {
24 #define RTD_TYPE_WIFI "application/vnd.wfa.wsc"
25
26 #define UNSIGNED_BYTE_TO_INT_MASK 0xFF
27 #define WIFI_TYPE_LEN 2
28 #define WIFI_TYPE_TO_INT_MASK 0xFFFF
29
30 #define CREDENTIAL_FIELD_TYPE 0x100E
31 #define WIFI_SSID_TYPE 0x1045
32 #define WIFI_NETWORK_KEY_TYPE 0x1027
33 #define WIFI_AUTH_TYPE_TYPE 0x1003
34 #define WIFI_VENDOR_EXT_TYPE 0x1049
35
36 #define AUTH_TYPE_OPEN 0x0001
37 #define AUTH_TYPE_WPA_PSK 0x0002
38 #define AUTH_TYPE_WPA_EAP 0x0008
39 #define AUTH_TYPE_WPA2_EAP 0x0010
40 #define AUTH_TYPE_WPA2_PSK 0x0020
41 #define AUTH_TYPE_WPA_AND_WPA2_PSK 0x0022
42
43 #define RECORDS_MAX_SIZE 2000
44 #define NETWORK_KEY_MAX_SIZE 64
45 #define AUTH_TYPE_SIZE 2
46 #define MAX_VALUE_LENGTH 2000
47 #define MAX_PARSE_TIMES 16
48
49 using namespace OHOS::NFC::KITS;
50
NdefWifiDataParser()51 NdefWifiDataParser::NdefWifiDataParser()
52 {
53 }
54
GetTypeFromPayload(const std::string & src,uint32_t & offset)55 uint16_t NdefWifiDataParser::GetTypeFromPayload(const std::string& src, uint32_t &offset)
56 {
57 if (src.length() == 0 || (src.length() < (offset + WIFI_TYPE_LEN) * HEX_BYTE_LEN)) {
58 return 0;
59 }
60 unsigned char firstByte = KITS::NfcSdkCommon::GetByteFromHexStr(src, offset);
61 offset++;
62 unsigned char secondByte = KITS::NfcSdkCommon::GetByteFromHexStr(src, offset);
63 offset++;
64 uint8_t shift = 8; // 8 bits for one byte
65 return ((firstByte << shift) + secondByte) & WIFI_TYPE_TO_INT_MASK;
66 }
67
GetValueFromPayload(const std::string & payload,uint32_t & offset,uint16_t dataLen)68 std::string NdefWifiDataParser::GetValueFromPayload(const std::string& payload, uint32_t& offset, uint16_t dataLen)
69 {
70 if (dataLen > MAX_VALUE_LENGTH) {
71 return "";
72 }
73 if (dataLen * HEX_BYTE_LEN > (payload.length() - (offset * HEX_BYTE_LEN))) {
74 return "";
75 }
76 std::string data = payload.substr(offset * HEX_BYTE_LEN, dataLen * HEX_BYTE_LEN);
77 offset += dataLen;
78 return data;
79 }
80
SetKeyMgmt(std::string & keyMgmt,uint16_t authType)81 void NdefWifiDataParser::SetKeyMgmt(std::string& keyMgmt, uint16_t authType)
82 {
83 switch (authType) {
84 case AUTH_TYPE_OPEN:
85 keyMgmt = Wifi::KEY_MGMT_NONE;
86 break;
87 case AUTH_TYPE_WPA_PSK:
88 // fall-through
89 case AUTH_TYPE_WPA2_PSK:
90 // fall-through
91 case AUTH_TYPE_WPA_AND_WPA2_PSK:
92 keyMgmt = Wifi::KEY_MGMT_WPA_PSK;
93 break;
94 case AUTH_TYPE_WPA_EAP:
95 // fall-through
96 case AUTH_TYPE_WPA2_EAP:
97 keyMgmt = Wifi::KEY_MGMT_EAP;
98 break;
99 default:
100 break;
101 }
102 }
103
104 /*
105 * WIFI RECORD STRUCTURE
106 * Credential Type(2 BYTES) | Length(2 BYTES) | TLV data
107 * LTV data:
108 * TYPE(2 BYTES) | LEN(2 BYTES) | VALUE(LEN BYTES)
109 */
ParseWiFiPayload(const std::string & payload)110 std::shared_ptr<WifiData> NdefWifiDataParser::ParseWiFiPayload(const std::string& payload)
111 {
112 DebugLog("ParseWiFiPayload");
113 std::shared_ptr<WifiData> data = std::make_shared<WifiData>();
114 uint32_t offset = 0;
115 uint16_t type = GetTypeFromPayload(payload, offset);
116 uint16_t len = GetTypeFromPayload(payload, offset);
117 InfoLog("NdefWifiDataParser::ParseWiFiPayload, type: 0x%{public}X, len: %{public}d", type, len);
118 for (int i = 0; i < MAX_PARSE_TIMES && len > 0 && (offset * HEX_BYTE_LEN) < payload.length()
119 && type != CREDENTIAL_FIELD_TYPE; i++) {
120 offset += len;
121 type = GetTypeFromPayload(payload, offset);
122 len = GetTypeFromPayload(payload, offset);
123 InfoLog("NdefWifiDataParser::ParseWiFiPayload, type: 0x%{public}X, len: %{public}d", type, len);
124 }
125 if (len == 0) {
126 return data;
127 }
128 data->isValid_ = true;
129 if (!data->config_) {
130 data->config_ = new Wifi::WifiDeviceConfig();
131 }
132 while ((offset * HEX_BYTE_LEN) < payload.length()) {
133 type = GetTypeFromPayload(payload, offset);
134 len = GetTypeFromPayload(payload, offset);
135 InfoLog("NdefWifiDataParser::ParseWiFiPayload, type: 0x%{public}X, len: %{public}d", type, len);
136 switch (type) {
137 case WIFI_SSID_TYPE: {
138 std::string ssid = GetValueFromPayload(payload, offset, len);
139 if (ssid.empty()) {
140 ErrorLog("NdefWifiDataParser::ParseWiFiPayload, SSID error, "
141 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
142 data->isValid_ = false;
143 return data;
144 }
145 data->config_->ssid = KITS::NfcSdkCommon::HexArrayToStringWithoutChecking(ssid);
146 InfoLog("NdefWifiDataParser::ParseWiFiPayload, SSID: %{private}s", data->config_->ssid.c_str());
147 break;
148 }
149 case WIFI_NETWORK_KEY_TYPE: {
150 if (len > NETWORK_KEY_MAX_SIZE) {
151 ErrorLog("NdefWifiDataParser::ParseWiFiPayload, invalid network key length: %{public}d", len);
152 data->isValid_ = false;
153 return data;
154 }
155 std::string key = GetValueFromPayload(payload, offset, len);
156 if (key.empty()) {
157 ErrorLog("NdefWifiDataParser::ParseWiFiPayload, name error, "
158 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
159 data->isValid_ = false;
160 return data;
161 }
162 data->config_->preSharedKey = KITS::NfcSdkCommon::HexStringToAsciiString(key);
163 break;
164 }
165 case WIFI_AUTH_TYPE_TYPE: {
166 if (len != AUTH_TYPE_SIZE) {
167 ErrorLog("NdefWifiDataParser::ParseWiFiPayload, invalid auth type len");
168 data->isValid_ = false;
169 return data;
170 }
171 uint16_t authType = GetTypeFromPayload(payload, offset);
172 if (authType == 0) {
173 ErrorLog("NdefWifiDataParser::ParseWiFiPayload, invalid auth type value");
174 data->isValid_ = false;
175 return data;
176 }
177 SetKeyMgmt(data->config_->keyMgmt, authType);
178 InfoLog("NdefWifiDataParser::ParseWiFiPayload, keyMgmt: %{public}s, authType: %{public}d",
179 data->config_->keyMgmt.c_str(), authType);
180 break;
181 }
182 case WIFI_VENDOR_EXT_TYPE: {
183 std::string vendorPayload = GetValueFromPayload(payload, offset, len);
184 if (vendorPayload.empty()) {
185 ErrorLog("NdefWifiDataParser::ParseWiFiPayload, vendor error, "
186 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
187 data->isValid_ = false;
188 return data;
189 }
190 data->vendorPayload_ = vendorPayload;
191 break;
192 }
193 default: {
194 offset += len;
195 InfoLog("NdefWifiDataParser::ParseWiFiPayload, unknown type = 0x%{public}X", type);
196 break;
197 }
198 }
199 }
200 if (!data->config_->ssid.empty()) {
201 if (data->config_->keyMgmt == Wifi::KEY_MGMT_NONE) {
202 WarnLog("key should be null when keyMgmt is NONE");
203 data->config_->preSharedKey = "";
204 } else if (data->config_->preSharedKey.empty()) {
205 ErrorLog("key should not be null when keyMgmt is not NONE");
206 data->isValid_ = false;
207 }
208 }
209 if (!data->isValid_ && data->config_) {
210 delete data->config_;
211 data->config_ = nullptr;
212 }
213 InfoLog("parse end, valid: %{public}d", data->isValid_);
214 return data;
215 }
216
CheckWifiRecord(const std::string & msg)217 std::shared_ptr<WifiData> NdefWifiDataParser::CheckWifiRecord(const std::string& msg)
218 {
219 if (msg.empty()) {
220 ErrorLog("NdefWifiDataParser::CheckWifiRecord: msg is empty");
221 return std::make_shared<WifiData>();
222 }
223 std::shared_ptr<NdefMessage> ndef = NdefMessage::GetNdefMessage(msg);
224 if (ndef == nullptr || (ndef->GetNdefRecords().size() == 0)) {
225 ErrorLog("NdefWifiDataParser::CheckWifiRecord: ndef is null");
226 return std::make_shared<WifiData>();
227 }
228 std::vector<std::shared_ptr<NdefRecord>> records = ndef->GetNdefRecords();
229 if (records.size() > RECORDS_MAX_SIZE) {
230 ErrorLog("NdefWifiDataParser::CheckWifiRecord: invalid records size");
231 return std::make_shared<WifiData>();
232 }
233 for (std::shared_ptr<NdefRecord> record : records) {
234 if (!record) {
235 ErrorLog("NdefWifiDataParser::CheckWifiRecord: record is null");
236 return std::make_shared<WifiData>();
237 }
238 if (record->tagRtdType_.compare(KITS::NfcSdkCommon::StringToHexString(RTD_TYPE_WIFI)) == 0) {
239 return ParseWiFiPayload(record->payload_);
240 }
241 }
242 return std::make_shared<WifiData>();
243 }
244 } // namespace TAG
245 } // namespace NFC
246 } // namespace OHOS