hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/nfc/st21nfca/se.c
....@@ -1,17 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
3
- *
4
- * This program is free software; you can redistribute it and/or modify it
5
- * under the terms and conditions of the GNU General Public License,
6
- * version 2, as published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope that it will be useful,
9
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- * GNU General Public License for more details.
12
- *
13
- * You should have received a copy of the GNU General Public License
14
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
154 */
165
176 #include <net/nfc/hci.h>
....@@ -252,7 +241,7 @@
252241 }
253242 EXPORT_SYMBOL(st21nfca_hci_se_io);
254243
255
-static void st21nfca_se_wt_timeout(struct timer_list *t)
244
+static void st21nfca_se_wt_work(struct work_struct *work)
256245 {
257246 /*
258247 * No answer from the secure element
....@@ -265,8 +254,9 @@
265254 */
266255 /* hardware reset managed through VCC_UICC_OUT power supply */
267256 u8 param = 0x01;
268
- struct st21nfca_hci_info *info = from_timer(info, t,
269
- se_info.bwi_timer);
257
+ struct st21nfca_hci_info *info = container_of(work,
258
+ struct st21nfca_hci_info,
259
+ se_info.timeout_work);
270260
271261 pr_debug("\n");
272262
....@@ -282,6 +272,13 @@
282272 ST21NFCA_EVT_SE_HARD_RESET, &param, 1);
283273 }
284274 info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
275
+}
276
+
277
+static void st21nfca_se_wt_timeout(struct timer_list *t)
278
+{
279
+ struct st21nfca_hci_info *info = from_timer(info, t, se_info.bwi_timer);
280
+
281
+ schedule_work(&info->se_info.timeout_work);
285282 }
286283
287284 static void st21nfca_se_activation_timeout(struct timer_list *t)
....@@ -307,6 +304,8 @@
307304 int r = 0;
308305 struct device *dev = &hdev->ndev->dev;
309306 struct nfc_evt_transaction *transaction;
307
+ u32 aid_len;
308
+ u8 params_len;
310309
311310 pr_debug("connectivity gate event: %x\n", event);
312311
....@@ -315,34 +314,48 @@
315314 r = nfc_se_connectivity(hdev->ndev, host);
316315 break;
317316 case ST21NFCA_EVT_TRANSACTION:
318
- /*
319
- * According to specification etsi 102 622
317
+ /* According to specification etsi 102 622
320318 * 11.2.2.4 EVT_TRANSACTION Table 52
321319 * Description Tag Length
322320 * AID 81 5 to 16
323321 * PARAMETERS 82 0 to 255
322
+ *
323
+ * The key differences are aid storage length is variably sized
324
+ * in the packet, but fixed in nfc_evt_transaction, and that the aid_len
325
+ * is u8 in the packet, but u32 in the structure, and the tags in
326
+ * the packet are not included in nfc_evt_transaction.
327
+ *
328
+ * size in bytes: 1 1 5-16 1 1 0-255
329
+ * offset: 0 1 2 aid_len + 2 aid_len + 3 aid_len + 4
330
+ * member name: aid_tag(M) aid_len aid params_tag(M) params_len params
331
+ * example: 0x81 5-16 X 0x82 0-255 X
324332 */
325
- if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
326
- skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
333
+ if (skb->len < 2 || skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
327334 return -EPROTO;
328335
329
- transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
330
- skb->len - 2, GFP_KERNEL);
336
+ aid_len = skb->data[1];
337
+
338
+ if (skb->len < aid_len + 4 || aid_len > sizeof(transaction->aid))
339
+ return -EPROTO;
340
+
341
+ params_len = skb->data[aid_len + 3];
342
+
343
+ /* Verify PARAMETERS tag is (82), and final check that there is enough
344
+ * space in the packet to read everything.
345
+ */
346
+ if ((skb->data[aid_len + 2] != NFC_EVT_TRANSACTION_PARAMS_TAG) ||
347
+ (skb->len < aid_len + 4 + params_len))
348
+ return -EPROTO;
349
+
350
+ transaction = devm_kzalloc(dev, sizeof(*transaction) + params_len, GFP_KERNEL);
331351 if (!transaction)
332352 return -ENOMEM;
333353
334
- transaction->aid_len = skb->data[1];
335
- memcpy(transaction->aid, &skb->data[2],
336
- transaction->aid_len);
354
+ transaction->aid_len = aid_len;
355
+ transaction->params_len = params_len;
337356
338
- /* Check next byte is PARAMETERS tag (82) */
339
- if (skb->data[transaction->aid_len + 2] !=
340
- NFC_EVT_TRANSACTION_PARAMS_TAG)
341
- return -EPROTO;
342
-
343
- transaction->params_len = skb->data[transaction->aid_len + 3];
344
- memcpy(transaction->params, skb->data +
345
- transaction->aid_len + 4, transaction->params_len);
357
+ memcpy(transaction->aid, &skb->data[2], aid_len);
358
+ memcpy(transaction->params, &skb->data[aid_len + 4], params_len);
346359
347360 r = nfc_se_transaction(hdev->ndev, host, transaction);
348361 break;
....@@ -366,6 +379,7 @@
366379 switch (event) {
367380 case ST21NFCA_EVT_TRANSMIT_DATA:
368381 del_timer_sync(&info->se_info.bwi_timer);
382
+ cancel_work_sync(&info->se_info.timeout_work);
369383 info->se_info.bwi_active = false;
370384 r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
371385 ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
....@@ -395,6 +409,7 @@
395409 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
396410
397411 init_completion(&info->se_info.req_completion);
412
+ INIT_WORK(&info->se_info.timeout_work, st21nfca_se_wt_work);
398413 /* initialize timers */
399414 timer_setup(&info->se_info.bwi_timer, st21nfca_se_wt_timeout, 0);
400415 info->se_info.bwi_active = false;
....@@ -422,6 +437,7 @@
422437 if (info->se_info.se_active)
423438 del_timer_sync(&info->se_info.se_active_timer);
424439
440
+ cancel_work_sync(&info->se_info.timeout_work);
425441 info->se_info.bwi_active = false;
426442 info->se_info.se_active = false;
427443 }