1 /*
2 * Copyright (C) 2023 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_oob_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 #define RTD_TYPE_BT_OOB "application/vnd.bluetooth.ep.oob"
24 #define RTD_TYPE_BLE_OOB "application/vnd.bluetooth.le.oob"
25
26 #define UNSIGNED_BYTE_TO_INT_MASK 0xFF
27
28 #define CARRIER_PWR_STA_INACTIVE 0
29 #define CARRIER_PWR_STA_ACTIVE 1
30 #define CARRIER_PWR_STA_ACTIVATING 2
31 #define CARRIER_PWR_STA_UNKNOWN 3
32
33 #define BT_OOB_TYPE_MAC 0x1B
34 #define BT_OOB_TYPE_LE_ROLE 0x1C
35 #define BT_OOB_TYPE_LONG_LOCAL_NAME 0x09
36 #define BT_OOB_TYPE_SHORT_LOCAL_NAME 0x08
37 #define BT_OOB_TYPE_16_BIT_UUIDS_PARTIAL 0x02
38 #define BT_OOB_TYPE_16_BIT_UUIDS_COMPLETE 0x03
39 #define BT_OOB_TYPE_32_BIT_UUIDS_PARTIAL 0x04
40 #define BT_OOB_TYPE_32_BIT_UUIDS_COMPLETE 0x05
41 #define BT_OOB_TYPE_128_BIT_UUIDS_PARTIAL 0x06
42 #define BT_OOB_TYPE_128_BIT_UUIDS_COMPLETE 0x07
43 #define BT_OOB_TYPE_CLASS_OF_DEVICE 0x0D
44 #define BT_OOB_TYPE_SEC_MGR_TK 0x10
45 #define BT_OOB_TYPE_APPEARANCE 0x19
46 #define BT_OOB_TYPE_LE_SC_CONFIRMATION 0x22
47 #define BT_OOB_TYPE_LE_SC_RANDOM 0x23
48 #define BT_OOB_TYPE_VENDOR 0xFF
49
50 #define BT_OOB_LE_ROLE_CENTRAL_ONLY 0x01
51
52 #define SEC_MGR_TK_SIZE 16
53 #define SEC_MGR_LE_SC_C_SIZE 16
54 #define SEC_MGR_LE_SC_R_SIZE 16
55 #define CLASS_OF_DEVICE_SIZE 3
56 #define VENDOR_SERIAL_NUM_SIZE 2
57
58 #define UUID_BYTES_16_BIT_LEN 2
59 #define UUID_BYTES_32_BIT_LEN 4
60 #define UUID_BYTES_128_BIT_LEN 16
61
62 using namespace OHOS::NFC::KITS;
63
NdefBtOobDataParser()64 NdefBtOobDataParser::NdefBtOobDataParser()
65 {
66 }
67
GetBtMacFromPayload(const std::string & payload,uint32_t & offset)68 std::string NdefBtOobDataParser::GetBtMacFromPayload(const std::string& payload, uint32_t& offset)
69 {
70 uint32_t macLen = 6;
71 if (macLen * HEX_BYTE_LEN > payload.length() - (offset * HEX_BYTE_LEN)) {
72 ErrorLog("NdefBtOobDataParser::GetBtMacFromPayload, data error, "
73 "payload len %{public}lu offset.%{public}d", payload.length(), offset);
74 return "";
75 }
76 std::string mac = payload.substr(offset * HEX_BYTE_LEN, macLen * HEX_BYTE_LEN);
77 offset += macLen;
78 return mac;
79 }
80
GetDataFromPayload(const std::string & payload,uint32_t & offset,uint32_t datalen)81 std::string NdefBtOobDataParser::GetDataFromPayload(const std::string& payload, uint32_t& offset, uint32_t datalen)
82 {
83 if (datalen * HEX_BYTE_LEN > (payload.length() - (offset * HEX_BYTE_LEN))) {
84 return "";
85 }
86 std::string data = payload.substr(offset * HEX_BYTE_LEN, datalen * HEX_BYTE_LEN);
87 offset += datalen;
88 return data;
89 }
90
GetUuidFromPayload(const std::string & payload,uint32_t & offset,uint32_t type,uint32_t len)91 std::string NdefBtOobDataParser::GetUuidFromPayload(const std::string& payload, uint32_t& offset,
92 uint32_t type, uint32_t len)
93 {
94 // uuids can have several groups, uuidsSize is the size of each group
95 uint32_t uuidSize;
96 switch (type) {
97 case BT_OOB_TYPE_16_BIT_UUIDS_PARTIAL:
98 case BT_OOB_TYPE_16_BIT_UUIDS_COMPLETE:
99 uuidSize = UUID_BYTES_16_BIT_LEN;
100 break;
101 case BT_OOB_TYPE_32_BIT_UUIDS_PARTIAL:
102 case BT_OOB_TYPE_32_BIT_UUIDS_COMPLETE:
103 uuidSize = UUID_BYTES_32_BIT_LEN;
104 break;
105 case BT_OOB_TYPE_128_BIT_UUIDS_PARTIAL:
106 case BT_OOB_TYPE_128_BIT_UUIDS_COMPLETE:
107 uuidSize = UUID_BYTES_128_BIT_LEN;
108 break;
109 default:
110 ErrorLog("NdefBtOobDataParser::GetUuidFromPayload, unknown type of UUID");
111 return "";
112 }
113 if (len == 0 || (len % uuidSize != 0) || len * HEX_BYTE_LEN > (payload.length() - (offset * HEX_BYTE_LEN))) {
114 return "";
115 }
116 std::string uuid = payload.substr(offset * HEX_BYTE_LEN, len * HEX_BYTE_LEN);
117 offset += len;
118 return uuid;
119 }
120
121 /*
122 * BT OOB RECORD STRUCTURE
123 * BtOobLen(2 BYTEs) | MacAddr(6 BYTES, reverted) | LTV data
124 * LTV data:
125 * LEN(1 BYTE) |TYPE(1 BYTE) |VALUE(LEN -1 BYTES)
126 */
ParseBtOobRecord(const std::string & payload)127 std::shared_ptr<BtOobData> NdefBtOobDataParser::ParseBtOobRecord(const std::string& payload)
128 {
129 std::shared_ptr<BtOobData> data = std::make_shared<BtOobData>();
130 data->isValid_ = false;
131 uint32_t offset = 0; // offset is for byte parse position, payload is hex string
132 // to compare need to * HEX_BYTE_LEN
133
134 uint32_t btOobLen = 2;
135 offset += btOobLen;
136 std::string macAddress = GetBtMacFromPayload(payload, offset);
137 if (macAddress.empty()) {
138 ErrorLog("NdefBtOobDataParser::ParseBtOobRecord, macAddress error, "
139 "payload .len %{public}lu offset.%{public}d", payload.length(), offset);
140 return data;
141 }
142 data->macAddress_ = macAddress;
143 data->isValid_ = true;
144
145 while ((offset * HEX_BYTE_LEN) < payload.length()) {
146 bool isValid = false;
147 std::string name;
148 uint32_t len = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
149 uint32_t type = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
150 switch (type) {
151 case BT_OOB_TYPE_SHORT_LOCAL_NAME: {
152 if (len < 1) {
153 ErrorLog("NdefBtOobDataParser::ParseBtOobRecord, invalid local name len. ");
154 data->isValid_ = false;
155 return data;
156 }
157 name = GetDataFromPayload(payload, offset, len - 1);
158 if (name.empty()) {
159 ErrorLog("NdefBtOobDataParser::ParseBtOobRecord, name error, "
160 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
161 break;
162 }
163 data->name_ = name;
164 isValid = true;
165 break;
166 }
167 case BT_OOB_TYPE_LONG_LOCAL_NAME: {
168 if (!data->name_.empty()) {
169 offset += (len - 1);
170 break; // already contains short name
171 }
172 if (len < 1) {
173 ErrorLog("NdefBtOobDataParser::ParseBtOobRecord, invalid long local name len. ");
174 data->isValid_ = false;
175 return data;
176 }
177 name = GetDataFromPayload(payload, offset, len - 1);
178 if (name.empty()) {
179 ErrorLog("NdefBtOobDataParser::ParseBtOobRecord, name error, "
180 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
181 break;
182 }
183 data->name_ = name;
184 isValid = true;
185 break;
186 }
187 case BT_OOB_TYPE_16_BIT_UUIDS_PARTIAL:
188 case BT_OOB_TYPE_16_BIT_UUIDS_COMPLETE:
189 case BT_OOB_TYPE_32_BIT_UUIDS_PARTIAL:
190 case BT_OOB_TYPE_32_BIT_UUIDS_COMPLETE:
191 case BT_OOB_TYPE_128_BIT_UUIDS_PARTIAL:
192 case BT_OOB_TYPE_128_BIT_UUIDS_COMPLETE: {
193 data->uuids_ = GetUuidFromPayload(payload, offset, type, len - 1);
194 if (!data->uuids_.empty()) {
195 isValid = true;
196 }
197 break;
198 }
199 case BT_OOB_TYPE_CLASS_OF_DEVICE: {
200 if (len - 1 != CLASS_OF_DEVICE_SIZE) {
201 ErrorLog("NdefBtOobDataParser::ParseBtOobRecord, invalid class of Device len");
202 break;
203 }
204 offset += CLASS_OF_DEVICE_SIZE;
205 isValid = true;
206 break;
207 }
208 case BT_OOB_TYPE_VENDOR: {
209 std::string vendorPayload = GetDataFromPayload(payload, offset, len - 1);
210 if (vendorPayload.empty()) {
211 ErrorLog("NdefBtOobDataParser::ParseBtOobRecord, vendor error, "
212 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
213 break;
214 }
215 data->vendorPayload_ = vendorPayload;
216 isValid = true;
217 break;
218 }
219 default: {
220 offset += (len - 1);
221 ErrorLog("NdefBtOobDataParser::ParseBtOobRecord, unknown type = %{public}d", type);
222 break;
223 }
224 }
225 if (!isValid) {
226 ErrorLog("NdefBtOobDataParser::ParseBtOobRecord, vendor error, "
227 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
228 data->isValid_ = false;
229 return data;
230 }
231 }
232 return data;
233 }
234
ParseBleOobRecord(const std::string & payload)235 std::shared_ptr<BtOobData> NdefBtOobDataParser::ParseBleOobRecord(const std::string& payload)
236 {
237 std::shared_ptr<BtOobData> data = std::make_shared<BtOobData>();
238 data->isValid_ = false;
239 uint32_t offset = 0; // offset is for byte parse position, payload is hex string
240 // to compare need to * HEX_BYTE_LEN
241
242 std::string bdaddr = "";
243 unsigned char role = 0xF; // invalid default
244 std::string leScC = "";
245 std::string leScR = "";
246 std::string name = "";
247 std::string secMgrTK = "";
248 std::string macAddress = "";
249 while ((offset * HEX_BYTE_LEN) < payload.length()) {
250 uint32_t len = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
251 uint32_t type = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
252 switch (type) {
253 case BT_OOB_TYPE_MAC: {
254 uint32_t bdaddrLen = 7; // 6 bytes for mac, 1 for address type
255 bdaddr = GetDataFromPayload(payload, offset, bdaddrLen);
256 if (bdaddr.empty()) {
257 ErrorLog("NdefBtOobDataParser::ParseBleOobRecord, bdaddr error, "
258 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
259 break;
260 }
261 macAddress = GetBtMacFromPayload(payload, offset);
262 if (macAddress.empty()) {
263 ErrorLog("NdefBtOobDataParser::ParseBleOobRecord, macAddress error, "
264 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
265 break;
266 }
267 offset++; // advance over random byte
268 data->isValid_ = true;
269 break;
270 }
271 case BT_OOB_TYPE_LE_ROLE: {
272 role = NfcSdkCommon::GetByteFromHexStr(payload, offset++) & UNSIGNED_BYTE_TO_INT_MASK;
273 if (role == BT_OOB_LE_ROLE_CENTRAL_ONLY) {
274 data->isValid_ = false;
275 return data;
276 }
277 break;
278 }
279 case BT_OOB_TYPE_LONG_LOCAL_NAME: {
280 name = GetDataFromPayload(payload, offset, len - 1);
281 if (name.empty()) {
282 ErrorLog("NdefBtOobDataParser::ParseBleOobRecord, name error, "
283 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
284 break;
285 }
286 data->name_ = name;
287 break;
288 }
289 case BT_OOB_TYPE_SEC_MGR_TK: {
290 if (len - 1 != SEC_MGR_TK_SIZE) {
291 ErrorLog("NdefBtOobDataParser::ParseBleOobRecord, SM TK len error, should be %{public}d",
292 SEC_MGR_TK_SIZE);
293 break;
294 }
295 secMgrTK = GetDataFromPayload(payload, offset, len);
296 if (leScC.empty()) {
297 ErrorLog("NdefBtOobDataParser::ParseBleOobRecord, secMgrTK error, "
298 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
299 break;
300 }
301 break;
302 }
303 case BT_OOB_TYPE_LE_SC_CONFIRMATION: {
304 if (len - 1 != SEC_MGR_LE_SC_C_SIZE) {
305 ErrorLog("NdefBtOobDataParser::ParseBleOobRecord, LE SC Confirmation len error, "
306 "should be %{public}d", SEC_MGR_LE_SC_C_SIZE);
307 break;
308 }
309 leScC = GetDataFromPayload(payload, offset, len - 1);
310 if (leScC.empty()) {
311 ErrorLog("NdefBtOobDataParser::ParseBleOobRecord, leScC Confirmation error, "
312 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
313 break;
314 }
315 break;
316 }
317 case BT_OOB_TYPE_LE_SC_RANDOM: {
318 if (len - 1 != SEC_MGR_LE_SC_R_SIZE) {
319 ErrorLog("NdefBtOobDataParser::ParseBleOobRecord, LE SC Random len error, should be %{public}d",
320 SEC_MGR_LE_SC_R_SIZE);
321 break;
322 }
323 leScR = GetDataFromPayload(payload, offset, len - 1);
324 if (leScR.empty()) {
325 ErrorLog("NdefBtOobDataParser::ParseBleOobRecord, leScC Random error, "
326 "payload len.%{public}lu offset.%{public}d type.%{public}d", payload.length(), offset, type);
327 break;
328 }
329 break;
330 }
331 default: {
332 offset += (len - 1);
333 break;
334 }
335 }
336 }
337 return data;
338 }
339
CheckBtRecord(const std::string & msg)340 std::shared_ptr<BtOobData> NdefBtOobDataParser::CheckBtRecord(const std::string& msg)
341 {
342 if (msg.empty()) {
343 ErrorLog("NdefBtOobDataParser::CheckBtRecord: msg is empty");
344 return std::make_shared<BtOobData>();
345 }
346 std::shared_ptr<NdefMessage> ndef = NdefMessage::GetNdefMessage(msg);
347 if (ndef == nullptr || (ndef->GetNdefRecords().size() == 0)) {
348 ErrorLog("NdefBtOobDataParser::CheckBtRecord: ndef is null");
349 return std::make_shared<BtOobData>();
350 }
351 std::shared_ptr<NdefRecord> record = ndef->GetNdefRecords()[0];
352 if (record == nullptr) {
353 ErrorLog("NdefBtOobDataParser::CheckBtRecord: record is null");
354 return std::make_shared<BtOobData>();
355 }
356
357 // Check BT OOB
358 if (record->tnf_ == NdefMessage::TNF_MIME_MEDIA &&
359 (record->tagRtdType_.compare(NfcSdkCommon::StringToHexString(RTD_TYPE_BT_OOB)) == 0)) {
360 InfoLog("NdefBtOobDataParser::CheckBtRecord: is bt oob");
361 return ParseBtOobRecord(record->payload_);
362 }
363
364 // Check BLE OOB
365 if (record->tnf_ == NdefMessage::TNF_MIME_MEDIA &&
366 (record->tagRtdType_.compare(NfcSdkCommon::StringToHexString(RTD_TYPE_BLE_OOB)) == 0)) {
367 InfoLog("NdefBtOobDataParser::CheckBtRecord: is ble oob, currently not supported");
368 return std::make_shared<BtOobData>();
369 }
370
371 // Check Handover Select, followed by a BT OOB record
372 if (record->tnf_ == NdefMessage::TNF_WELL_KNOWN &&
373 (record->tagRtdType_.compare(NdefMessage::GetTagRtdType(NdefMessage::RTD_HANDOVER_SELECT)) == 0)) {
374 InfoLog("NdefBtOobDataParser::CheckBtRecord: is handover select, currently not supported");
375 return std::make_shared<BtOobData>();
376 }
377 return std::make_shared<BtOobData>();
378 }
379 } // namespace NFC
380 } // namespace OHOS