hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
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>
....@@ -247,12 +236,18 @@
247236 ST21NFCA_EVT_TRANSMIT_DATA,
248237 apdu, apdu_length);
249238 default:
239
+ /* Need to free cb_context here as at the moment we can't
240
+ * clearly indicate to the caller if the callback function
241
+ * would be called (and free it) or not. In both cases a
242
+ * negative value may be returned to the caller.
243
+ */
244
+ kfree(cb_context);
250245 return -ENODEV;
251246 }
252247 }
253248 EXPORT_SYMBOL(st21nfca_hci_se_io);
254249
255
-static void st21nfca_se_wt_timeout(struct timer_list *t)
250
+static void st21nfca_se_wt_work(struct work_struct *work)
256251 {
257252 /*
258253 * No answer from the secure element
....@@ -265,8 +260,9 @@
265260 */
266261 /* hardware reset managed through VCC_UICC_OUT power supply */
267262 u8 param = 0x01;
268
- struct st21nfca_hci_info *info = from_timer(info, t,
269
- se_info.bwi_timer);
263
+ struct st21nfca_hci_info *info = container_of(work,
264
+ struct st21nfca_hci_info,
265
+ se_info.timeout_work);
270266
271267 pr_debug("\n");
272268
....@@ -282,6 +278,13 @@
282278 ST21NFCA_EVT_SE_HARD_RESET, &param, 1);
283279 }
284280 info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
281
+}
282
+
283
+static void st21nfca_se_wt_timeout(struct timer_list *t)
284
+{
285
+ struct st21nfca_hci_info *info = from_timer(info, t, se_info.bwi_timer);
286
+
287
+ schedule_work(&info->se_info.timeout_work);
285288 }
286289
287290 static void st21nfca_se_activation_timeout(struct timer_list *t)
....@@ -307,6 +310,8 @@
307310 int r = 0;
308311 struct device *dev = &hdev->ndev->dev;
309312 struct nfc_evt_transaction *transaction;
313
+ u32 aid_len;
314
+ u8 params_len;
310315
311316 pr_debug("connectivity gate event: %x\n", event);
312317
....@@ -315,34 +320,48 @@
315320 r = nfc_se_connectivity(hdev->ndev, host);
316321 break;
317322 case ST21NFCA_EVT_TRANSACTION:
318
- /*
319
- * According to specification etsi 102 622
323
+ /* According to specification etsi 102 622
320324 * 11.2.2.4 EVT_TRANSACTION Table 52
321325 * Description Tag Length
322326 * AID 81 5 to 16
323327 * PARAMETERS 82 0 to 255
328
+ *
329
+ * The key differences are aid storage length is variably sized
330
+ * in the packet, but fixed in nfc_evt_transaction, and that the aid_len
331
+ * is u8 in the packet, but u32 in the structure, and the tags in
332
+ * the packet are not included in nfc_evt_transaction.
333
+ *
334
+ * size in bytes: 1 1 5-16 1 1 0-255
335
+ * offset: 0 1 2 aid_len + 2 aid_len + 3 aid_len + 4
336
+ * member name: aid_tag(M) aid_len aid params_tag(M) params_len params
337
+ * example: 0x81 5-16 X 0x82 0-255 X
324338 */
325
- if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
326
- skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
339
+ if (skb->len < 2 || skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
327340 return -EPROTO;
328341
329
- transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
330
- skb->len - 2, GFP_KERNEL);
342
+ aid_len = skb->data[1];
343
+
344
+ if (skb->len < aid_len + 4 || aid_len > sizeof(transaction->aid))
345
+ return -EPROTO;
346
+
347
+ params_len = skb->data[aid_len + 3];
348
+
349
+ /* Verify PARAMETERS tag is (82), and final check that there is enough
350
+ * space in the packet to read everything.
351
+ */
352
+ if ((skb->data[aid_len + 2] != NFC_EVT_TRANSACTION_PARAMS_TAG) ||
353
+ (skb->len < aid_len + 4 + params_len))
354
+ return -EPROTO;
355
+
356
+ transaction = devm_kzalloc(dev, sizeof(*transaction) + params_len, GFP_KERNEL);
331357 if (!transaction)
332358 return -ENOMEM;
333359
334
- transaction->aid_len = skb->data[1];
335
- memcpy(transaction->aid, &skb->data[2],
336
- transaction->aid_len);
360
+ transaction->aid_len = aid_len;
361
+ transaction->params_len = params_len;
337362
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);
363
+ memcpy(transaction->aid, &skb->data[2], aid_len);
364
+ memcpy(transaction->params, &skb->data[aid_len + 4], params_len);
346365
347366 r = nfc_se_transaction(hdev->ndev, host, transaction);
348367 break;
....@@ -366,6 +385,7 @@
366385 switch (event) {
367386 case ST21NFCA_EVT_TRANSMIT_DATA:
368387 del_timer_sync(&info->se_info.bwi_timer);
388
+ cancel_work_sync(&info->se_info.timeout_work);
369389 info->se_info.bwi_active = false;
370390 r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
371391 ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
....@@ -395,6 +415,7 @@
395415 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
396416
397417 init_completion(&info->se_info.req_completion);
418
+ INIT_WORK(&info->se_info.timeout_work, st21nfca_se_wt_work);
398419 /* initialize timers */
399420 timer_setup(&info->se_info.bwi_timer, st21nfca_se_wt_timeout, 0);
400421 info->se_info.bwi_active = false;
....@@ -422,6 +443,7 @@
422443 if (info->se_info.se_active)
423444 del_timer_sync(&info->se_info.se_active_timer);
424445
446
+ cancel_work_sync(&info->se_info.timeout_work);
425447 info->se_info.bwi_active = false;
426448 info->se_info.se_active = false;
427449 }