1 /*
2 * Copyright (C) 2023 - 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_bt_data_parser.h"
16
17 #include <string>
18 #include "loghelper.h"
19 #include "ndef_message.h"
20 #include "nfc_sdk_common.h"
21
22 namespace OHOS {
23 namespace NFC {
24 namespace TAG {
25 #define RTD_TYPE_BT "application/vnd.bluetooth.ep.oob"
26 #define RTD_TYPE_BLE "application/vnd.bluetooth.le.oob"
27
28 #define UNSIGNED_BYTE_TO_INT_MASK 0xFF
29
30 #define CARRIER_PWR_STA_INACTIVE 0
31 #define CARRIER_PWR_STA_ACTIVE 1
32 #define CARRIER_PWR_STA_ACTIVATING 2
33 #define CARRIER_PWR_STA_UNKNOWN 3
34
35 #define TYPE_MAC 0x1B
36 #define TYPE_LE_ROLE 0x1C
37 #define TYPE_LONG_LOCAL_NAME 0x09
38 #define TYPE_SHORT_LOCAL_NAME 0x08
39 #define TYPE_16_BIT_UUIDS_PARTIAL 0x02
40 #define TYPE_16_BIT_UUIDS_COMPLETE 0x03
41 #define TYPE_32_BIT_UUIDS_PARTIAL 0x04
42 #define TYPE_32_BIT_UUIDS_COMPLETE 0x05
43 #define TYPE_128_BIT_UUIDS_PARTIAL 0x06
44 #define TYPE_128_BIT_UUIDS_COMPLETE 0x07
45 #define TYPE_CLASS_OF_DEVICE 0x0D
46 #define TYPE_SEC_MGR_TK 0x10
47 #define TYPE_APPEARANCE 0x19
48 #define TYPE_LE_SC_CONFIRMATION 0x22
49 #define TYPE_LE_SC_RANDOM 0x23
50 #define TYPE_VENDOR 0xFF
51
52 #define BLE_ROLE_CENTRAL_ONLY 0x01
53
54 #define SEC_MGR_TK_SIZE 16
55 #define SEC_MGR_LE_SC_C_SIZE 16
56 #define SEC_MGR_LE_SC_R_SIZE 16
57 #define CLASS_OF_DEVICE_SIZE 3
58 #define VENDOR_SERIAL_NUM_SIZE 2
59 #define MAC_ADDR_SIZE 6
60
61 #define UUID_SEPARATOR "-"
62 #define MAC_SEPARATOR ":"
63 #define SHIFT_ONE_BYTE 8
64
65 using namespace OHOS::NFC::KITS;
66
NdefBtDataParser()67 NdefBtDataParser::NdefBtDataParser()
68 {
69 }
70
FormatBtMacAddr(const std::string & orgBtMac)71 std::string NdefBtDataParser::FormatBtMacAddr(const std::string& orgBtMac)
72 {
73 std::string result = "";
74 for (uint32_t i = MAC_ADDR_SIZE - 1; i > 0; i--) {
75 result += orgBtMac.substr(i * HEX_BYTE_LEN, HEX_BYTE_LEN);
76 result += MAC_SEPARATOR;
77 }
78 result += orgBtMac.substr(0, HEX_BYTE_LEN);
79 return result;
80 }
81
GetOrgBtMacFromPayload(const std::string & payload,uint32_t & offset)82 std::string NdefBtDataParser::GetOrgBtMacFromPayload(const std::string& payload, uint32_t& offset)
83 {
84 if (payload.length() < (offset * HEX_BYTE_LEN)) {
85 ErrorLog("NdefBtDataParser::GetBtMacFromPayload, payload.length error");
86 return "";
87 }
88 if (MAC_ADDR_SIZE * HEX_BYTE_LEN > payload.length() - (offset * HEX_BYTE_LEN)) {
89 ErrorLog("NdefBtDataParser::GetBtMacFromPayload, data error, "
90 "payload len %{public}lu offset.%{public}d", payload.length(), offset);
91 return "";
92 }
93 std::string mac = payload.substr(offset * HEX_BYTE_LEN, MAC_ADDR_SIZE * HEX_BYTE_LEN);
94 offset += MAC_ADDR_SIZE;
95 return mac;
96 }
97
GetBtDevClass(const std::string & payload,uint32_t & offset,Bluetooth::BluetoothDeviceClass & btClass)98 bool NdefBtDataParser::GetBtDevClass(const std::string& payload, uint32_t& offset,
99 Bluetooth::BluetoothDeviceClass& btClass)
100 {
101 if (payload.length() == 0 || (payload.length() < (offset + CLASS_OF_DEVICE_SIZE) * HEX_BYTE_LEN)) {
102 return false;
103 }
104 unsigned char firstByte = KITS::NfcSdkCommon::GetByteFromHexStr(payload, offset++);
105 unsigned char secondByte = KITS::NfcSdkCommon::GetByteFromHexStr(payload, offset++);
106 unsigned char thirdByte = KITS::NfcSdkCommon::GetByteFromHexStr(payload, offset++);
107 int devClass = (firstByte << (SHIFT_ONE_BYTE * 2)) + (secondByte << SHIFT_ONE_BYTE) + thirdByte;
108 btClass = Bluetooth::BluetoothDeviceClass(devClass);
109 return true;
110 }
111
RevertUuidStr(const std::string & uuid)112 std::string NdefBtDataParser::RevertUuidStr(const std::string& uuid)
113 {
114 std::string res = "";
115 uint32_t len = uuid.length();
116 if (len % HEX_BYTE_LEN != 0) {
117 ErrorLog("uuid len not even");
118 return res;
119 }
120 for (uint32_t i = len; i >= HEX_BYTE_LEN; i -= HEX_BYTE_LEN) {
121 res += uuid.substr(i - HEX_BYTE_LEN, HEX_BYTE_LEN);
122 }
123 return res;
124 }
125
FormatUuidTo128Bit(const std::string & uuid)126 Bluetooth::UUID NdefBtDataParser::FormatUuidTo128Bit(const std::string& uuid)
127 {
128 const uint32_t uuidPrefixLen = 8;
129 const uint32_t separatorPoz1 = 8;
130 const uint32_t separatorPoz2 = 12;
131 const uint32_t separatorPoz3 = 16;
132 const uint32_t separatorPoz4 = 20;
133 std::string uuidSubfix = Bluetooth::BLUETOOTH_UUID_BASE_UUID.substr(uuidPrefixLen,
134 Bluetooth::BLUETOOTH_UUID_BASE_UUID.length() - uuidPrefixLen);
135 std::string prefix16Bit = "0000";
136 std::string res = "";
137
138 if ((uuid.length() / HEX_BYTE_LEN) == Bluetooth::BLE_UUID_LEN_16) {
139 res = prefix16Bit + RevertUuidStr(uuid) + uuidSubfix;
140 } else if (uuid.length() == Bluetooth::BLE_UUID_LEN_32) {
141 res = RevertUuidStr(uuid) + uuidSubfix;
142 } else if (uuid.length() == Bluetooth::BLE_UUID_LEN_128) {
143 res = RevertUuidStr(uuid);
144 res.insert(separatorPoz4, UUID_SEPARATOR);
145 res.insert(separatorPoz3, UUID_SEPARATOR);
146 res.insert(separatorPoz2, UUID_SEPARATOR);
147 res.insert(separatorPoz1, UUID_SEPARATOR);
148 }
149 return Bluetooth::UUID::FromString(res);
150 }
151
GetDataFromPayload(const std::string & payload,uint32_t & offset,uint32_t dataLen)152 std::string NdefBtDataParser::GetDataFromPayload(const std::string& payload, uint32_t& offset, uint32_t dataLen)
153 {
154 if (dataLen * HEX_BYTE_LEN > (payload.length() - (offset * HEX_BYTE_LEN))) {
155 return "";
156 }
157 std::string data = payload.substr(offset * HEX_BYTE_LEN, dataLen * HEX_BYTE_LEN);
158 offset += dataLen;
159 return data;
160 }
161
GetUuidFromPayload(const std::string & payload,uint32_t & offset,uint32_t type,uint32_t len)162 std::vector<Bluetooth::UUID> NdefBtDataParser::GetUuidFromPayload(const std::string& payload, uint32_t& offset,
163 uint32_t type, uint32_t len)
164 {
165 // uuids can have several groups, uuidsSize is the size of each group
166 uint32_t uuidSize;
167 std::vector<Bluetooth::UUID> uuids;
168 switch (type) {
169 case TYPE_16_BIT_UUIDS_PARTIAL:
170 case TYPE_16_BIT_UUIDS_COMPLETE:
171 uuidSize = Bluetooth::BLE_UUID_LEN_16;
172 break;
173 case TYPE_32_BIT_UUIDS_PARTIAL:
174 case TYPE_32_BIT_UUIDS_COMPLETE:
175 uuidSize = Bluetooth::BLE_UUID_LEN_32;
176 break;
177 case TYPE_128_BIT_UUIDS_PARTIAL:
178 case TYPE_128_BIT_UUIDS_COMPLETE:
179 uuidSize = Bluetooth::BLE_UUID_LEN_128;
180 break;
181 default:
182 ErrorLog("NdefBtDataParser::GetUuidFromPayload, unknown type of UUID");
183 return uuids;
184 }
185 if (len == 0 || (len % uuidSize != 0) || len * HEX_BYTE_LEN > (payload.length() - (offset * HEX_BYTE_LEN))) {
186 return uuids;
187 }
188 uint32_t uuidNum = len / uuidSize;
189 for (uint32_t i = 0; i < uuidNum; i++) {
190 std::string uuid = payload.substr(offset * HEX_BYTE_LEN, uuidSize * HEX_BYTE_LEN);
191 offset += uuidSize;
192 uuids.push_back(FormatUuidTo128Bit(uuid));
193 }
194 return uuids;
195 }
196
197 /*
198 * BT RECORD STRUCTURE
199 * Len(2 BYTEs) | MacAddr(6 BYTES, reverted) | LTV data
200 * LTV data:
201 * LEN(1 BYTE) |TYPE(1 BYTE) |VALUE(LEN -1 BYTES)
202 */
ParseBtRecord(const std::string & payload)203 std::shared_ptr<BtData> NdefBtDataParser::ParseBtRecord(const std::string& payload)
204 {
205 std::shared_ptr<BtData> data = std::make_shared<BtData>();
206 data->isValid_ = false;
207 uint32_t offset = 0; // offset is for byte parse position, payload is hex string
208 // to compare need to * HEX_BYTE_LEN
209
210 uint32_t len = 2;
211 offset += len;
212 std::string macAddress = GetOrgBtMacFromPayload(payload, offset);
213 if (macAddress.empty()) {
214 ErrorLog("NdefBtDataParser::ParseBtRecord, macAddress error, "
215 "payload .len %{public}lu offset.%{public}d", payload.length(), offset);
216 return data;
217 }
218 data->macAddrOrg_ = macAddress;
219 data->macAddress_ = FormatBtMacAddr(macAddress);
220 data->isValid_ = true;
221
222 while ((offset * HEX_BYTE_LEN) < payload.length()) {
223 bool isValid = false;
224 std::string name;
225 uint32_t tvLen = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
226 uint32_t type = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
227 InfoLog("NdefBtDataParser::ParseBtRecord, len:%{public}d type:0x%{public}X", tvLen, type);
228 switch (type) {
229 case TYPE_SHORT_LOCAL_NAME: {
230 if (tvLen < 1) {
231 ErrorLog("NdefBtDataParser::ParseBtRecord, invalid local name len. ");
232 data->isValid_ = false;
233 return data;
234 }
235 name = GetDataFromPayload(payload, offset, tvLen - 1);
236 if (name.empty()) {
237 ErrorLog("NdefBtDataParser::ParseBtRecord, name error, "
238 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
239 break;
240 }
241 data->name_ = KITS::NfcSdkCommon::HexStringToAsciiString(name);
242 isValid = true;
243 break;
244 }
245 case TYPE_LONG_LOCAL_NAME: {
246 if (!data->name_.empty()) {
247 offset += (tvLen - 1);
248 break; // already contains short name
249 }
250 if (tvLen < 1) {
251 ErrorLog("NdefBtDataParser::ParseBtRecord, invalid long local name len. ");
252 data->isValid_ = false;
253 return data;
254 }
255 name = GetDataFromPayload(payload, offset, tvLen - 1);
256 if (name.empty()) {
257 ErrorLog("NdefBtDataParser::ParseBtRecord, name error, "
258 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
259 break;
260 }
261 data->name_ = KITS::NfcSdkCommon::HexStringToAsciiString(name);
262 isValid = true;
263 break;
264 }
265 case TYPE_16_BIT_UUIDS_PARTIAL:
266 case TYPE_16_BIT_UUIDS_COMPLETE:
267 case TYPE_32_BIT_UUIDS_PARTIAL:
268 case TYPE_32_BIT_UUIDS_COMPLETE:
269 case TYPE_128_BIT_UUIDS_PARTIAL:
270 case TYPE_128_BIT_UUIDS_COMPLETE: {
271 data->uuids_.clear();
272 data->uuids_ = GetUuidFromPayload(payload, offset, type, tvLen - 1);
273 if (!data->uuids_.empty()) {
274 isValid = true;
275 }
276 break;
277 }
278 case TYPE_CLASS_OF_DEVICE: {
279 if (tvLen - 1 != CLASS_OF_DEVICE_SIZE) {
280 ErrorLog("NdefBtDataParser::ParseBtRecord, invalid class of Device len");
281 break;
282 }
283 isValid = GetBtDevClass(payload, offset, data->btClass_);
284 break;
285 }
286 case TYPE_VENDOR: {
287 std::string vendorPayload = GetDataFromPayload(payload, offset, tvLen - 1);
288 if (vendorPayload.empty()) {
289 ErrorLog("NdefBtDataParser::ParseBtRecord, vendor error, "
290 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
291 break;
292 }
293 data->vendorPayload_ = vendorPayload;
294 isValid = true;
295 break;
296 }
297 default: {
298 ErrorLog("NdefBtDataParser::ParseBtRecord, unknown type = %{public}d", type);
299 if (tvLen < 1) {
300 ErrorLog("NdefBtDataParser::ParseBtRecord, invalid local name len. ");
301 return data;
302 }
303 offset += (tvLen - 1);
304 isValid = true;
305 break;
306 }
307 }
308 if (!isValid) {
309 ErrorLog("NdefBtDataParser::ParseBtRecord, vendor error, "
310 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
311 data->isValid_ = false;
312 return data;
313 }
314 }
315 return data;
316 }
317
ParseBleRecord(const std::string & payload)318 std::shared_ptr<BtData> NdefBtDataParser::ParseBleRecord(const std::string& payload)
319 {
320 std::shared_ptr<BtData> data = std::make_shared<BtData>();
321 data->isValid_ = false;
322 data->transport_ = Bluetooth::GATT_TRANSPORT_TYPE_LE;
323 uint32_t offset = 0; // offset is for byte parse position, payload is hex string
324 // to compare need to * HEX_BYTE_LEN
325
326 std::string bdaddr = "";
327 unsigned char role = 0xF; // invalid default
328 std::string leScC = "";
329 std::string leScR = "";
330 std::string name = "";
331 std::string secMgrTK = "";
332 std::string macAddress = "";
333 while ((offset * HEX_BYTE_LEN) < payload.length()) {
334 uint32_t len = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
335 uint32_t type = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
336 switch (type) {
337 case TYPE_MAC: {
338 uint32_t bdaddrLen = 7; // 6 bytes for mac, 1 for address type
339 bdaddr = GetDataFromPayload(payload, offset, bdaddrLen);
340 if (bdaddr.empty()) {
341 ErrorLog("NdefBtDataParser::ParseBleRecord, bdaddr error, "
342 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
343 break;
344 }
345 std::string mac = GetOrgBtMacFromPayload(payload, offset);
346 if (mac.empty()) {
347 ErrorLog("NdefBtDataParser::ParseBleRecord, macAddress error, "
348 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
349 break;
350 }
351 macAddress = FormatBtMacAddr(mac);
352 offset++; // advance over random byte
353 data->isValid_ = true;
354 break;
355 }
356 case TYPE_LE_ROLE: {
357 role = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
358 if (role == BLE_ROLE_CENTRAL_ONLY) {
359 data->isValid_ = false;
360 return data;
361 }
362 break;
363 }
364 case TYPE_LONG_LOCAL_NAME: {
365 name = GetDataFromPayload(payload, offset, len - 1);
366 if (name.empty()) {
367 ErrorLog("NdefBtDataParser::ParseBleRecord, name error, "
368 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
369 break;
370 }
371 data->name_ = KITS::NfcSdkCommon::HexStringToAsciiString(name);
372 break;
373 }
374 case TYPE_SEC_MGR_TK: {
375 if (len - 1 != SEC_MGR_TK_SIZE) {
376 ErrorLog("NdefBtDataParser::ParseBleRecord, SM TK len error, should be %{public}d",
377 SEC_MGR_TK_SIZE);
378 break;
379 }
380 secMgrTK = GetDataFromPayload(payload, offset, len);
381 if (leScC.empty()) {
382 ErrorLog("NdefBtDataParser::ParseBleRecord, secMgrTK error, "
383 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
384 break;
385 }
386 break;
387 }
388 case TYPE_LE_SC_CONFIRMATION: {
389 if (len - 1 != SEC_MGR_LE_SC_C_SIZE) {
390 ErrorLog("NdefBtDataParser::ParseBleRecord, LE SC Confirmation len error, "
391 "should be %{public}d", SEC_MGR_LE_SC_C_SIZE);
392 break;
393 }
394 leScC = GetDataFromPayload(payload, offset, len - 1);
395 if (leScC.empty()) {
396 ErrorLog("NdefBtDataParser::ParseBleRecord, leScC Confirmation error, "
397 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
398 break;
399 }
400 break;
401 }
402 case TYPE_LE_SC_RANDOM: {
403 if (len - 1 != SEC_MGR_LE_SC_R_SIZE) {
404 ErrorLog("NdefBtDataParser::ParseBleRecord, LE SC Random len error, should be %{public}d",
405 SEC_MGR_LE_SC_R_SIZE);
406 break;
407 }
408 leScR = GetDataFromPayload(payload, offset, len - 1);
409 if (leScR.empty()) {
410 ErrorLog("NdefBtDataParser::ParseBleRecord, leScC Random error, "
411 "payload len.%{public}lu offset.%{public}d type.0x%{public}X", payload.length(), offset, type);
412 break;
413 }
414 break;
415 }
416 default: {
417 offset += (len - 1);
418 break;
419 }
420 }
421 }
422 return data;
423 }
424
CheckBtRecord(const std::string & msg)425 std::shared_ptr<BtData> NdefBtDataParser::CheckBtRecord(const std::string& msg)
426 {
427 if (msg.empty()) {
428 ErrorLog("NdefBtDataParser::CheckBtRecord: msg is empty");
429 return std::make_shared<BtData>();
430 }
431 std::shared_ptr<NdefMessage> ndef = NdefMessage::GetNdefMessage(msg);
432 if (ndef == nullptr || (ndef->GetNdefRecords().size() == 0)) {
433 ErrorLog("NdefBtDataParser::CheckBtRecord: ndef is null");
434 return std::make_shared<BtData>();
435 }
436 std::shared_ptr<NdefRecord> record = ndef->GetNdefRecords()[0];
437 if (record == nullptr) {
438 ErrorLog("NdefBtDataParser::CheckBtRecord: record is null");
439 return std::make_shared<BtData>();
440 }
441
442 if (record->payload_.length() == 0) {
443 ErrorLog("NdefBtDataParser::CheckBtRecord: payload.length is 0");
444 return std::make_shared<BtData>();
445 }
446
447 // Check BT
448 if (record->tnf_ == NdefMessage::TNF_MIME_MEDIA &&
449 (record->tagRtdType_.compare(NfcSdkCommon::StringToHexString(RTD_TYPE_BT)) == 0)) {
450 InfoLog("NdefBtDataParser::CheckBtRecord: is bt");
451 return ParseBtRecord(record->payload_);
452 }
453
454 // Check BLE
455 if (record->tnf_ == NdefMessage::TNF_MIME_MEDIA &&
456 (record->tagRtdType_.compare(NfcSdkCommon::StringToHexString(RTD_TYPE_BLE)) == 0)) {
457 InfoLog("NdefBtDataParser::CheckBtRecord: is ble, currently not supported");
458 return std::make_shared<BtData>();
459 }
460
461 // Check Handover Select, followed by a BT record
462 if (record->tnf_ == NdefMessage::TNF_WELL_KNOWN &&
463 (record->tagRtdType_.compare(NdefMessage::GetTagRtdType(NdefMessage::RTD_HANDOVER_SELECT)) == 0)) {
464 InfoLog("NdefBtDataParser::CheckBtRecord: is handover select, currently not supported");
465 return std::make_shared<BtData>();
466 }
467 return std::make_shared<BtData>();
468 }
469
IsVendorPayloadValid(const std::string & payload)470 bool NdefBtDataParser::IsVendorPayloadValid(const std::string& payload)
471 {
472 int len = payload.length();
473 if (len % HEX_BYTE_LEN != 0) {
474 ErrorLog("BT vendor payload len invalid");
475 return false;
476 }
477 int bytesLen = len / HEX_BYTE_LEN;
478 if (bytesLen > VENDOR_PAYLOAD_MAX_LEN) {
479 ErrorLog("BT vendor payload len exceeds, bytesLen = %{public}d", bytesLen);
480 return false;
481 }
482 return true;
483 }
484 } // namespace TAG
485 } // namespace NFC
486 } // namespace OHOS