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