.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * 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/>. |
---|
15 | 4 | */ |
---|
16 | 5 | |
---|
17 | 6 | #include <net/nfc/hci.h> |
---|
.. | .. |
---|
247 | 236 | ST21NFCA_EVT_TRANSMIT_DATA, |
---|
248 | 237 | apdu, apdu_length); |
---|
249 | 238 | 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); |
---|
250 | 245 | return -ENODEV; |
---|
251 | 246 | } |
---|
252 | 247 | } |
---|
253 | 248 | EXPORT_SYMBOL(st21nfca_hci_se_io); |
---|
254 | 249 | |
---|
255 | | -static void st21nfca_se_wt_timeout(struct timer_list *t) |
---|
| 250 | +static void st21nfca_se_wt_work(struct work_struct *work) |
---|
256 | 251 | { |
---|
257 | 252 | /* |
---|
258 | 253 | * No answer from the secure element |
---|
.. | .. |
---|
265 | 260 | */ |
---|
266 | 261 | /* hardware reset managed through VCC_UICC_OUT power supply */ |
---|
267 | 262 | 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); |
---|
270 | 266 | |
---|
271 | 267 | pr_debug("\n"); |
---|
272 | 268 | |
---|
.. | .. |
---|
282 | 278 | ST21NFCA_EVT_SE_HARD_RESET, ¶m, 1); |
---|
283 | 279 | } |
---|
284 | 280 | 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); |
---|
285 | 288 | } |
---|
286 | 289 | |
---|
287 | 290 | static void st21nfca_se_activation_timeout(struct timer_list *t) |
---|
.. | .. |
---|
307 | 310 | int r = 0; |
---|
308 | 311 | struct device *dev = &hdev->ndev->dev; |
---|
309 | 312 | struct nfc_evt_transaction *transaction; |
---|
| 313 | + u32 aid_len; |
---|
| 314 | + u8 params_len; |
---|
310 | 315 | |
---|
311 | 316 | pr_debug("connectivity gate event: %x\n", event); |
---|
312 | 317 | |
---|
.. | .. |
---|
315 | 320 | r = nfc_se_connectivity(hdev->ndev, host); |
---|
316 | 321 | break; |
---|
317 | 322 | case ST21NFCA_EVT_TRANSACTION: |
---|
318 | | - /* |
---|
319 | | - * According to specification etsi 102 622 |
---|
| 323 | + /* According to specification etsi 102 622 |
---|
320 | 324 | * 11.2.2.4 EVT_TRANSACTION Table 52 |
---|
321 | 325 | * Description Tag Length |
---|
322 | 326 | * AID 81 5 to 16 |
---|
323 | 327 | * 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 |
---|
324 | 338 | */ |
---|
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) |
---|
327 | 340 | return -EPROTO; |
---|
328 | 341 | |
---|
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); |
---|
331 | 357 | if (!transaction) |
---|
332 | 358 | return -ENOMEM; |
---|
333 | 359 | |
---|
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; |
---|
337 | 362 | |
---|
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); |
---|
346 | 365 | |
---|
347 | 366 | r = nfc_se_transaction(hdev->ndev, host, transaction); |
---|
348 | 367 | break; |
---|
.. | .. |
---|
366 | 385 | switch (event) { |
---|
367 | 386 | case ST21NFCA_EVT_TRANSMIT_DATA: |
---|
368 | 387 | del_timer_sync(&info->se_info.bwi_timer); |
---|
| 388 | + cancel_work_sync(&info->se_info.timeout_work); |
---|
369 | 389 | info->se_info.bwi_active = false; |
---|
370 | 390 | r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE, |
---|
371 | 391 | ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0); |
---|
.. | .. |
---|
395 | 415 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
---|
396 | 416 | |
---|
397 | 417 | init_completion(&info->se_info.req_completion); |
---|
| 418 | + INIT_WORK(&info->se_info.timeout_work, st21nfca_se_wt_work); |
---|
398 | 419 | /* initialize timers */ |
---|
399 | 420 | timer_setup(&info->se_info.bwi_timer, st21nfca_se_wt_timeout, 0); |
---|
400 | 421 | info->se_info.bwi_active = false; |
---|
.. | .. |
---|
422 | 443 | if (info->se_info.se_active) |
---|
423 | 444 | del_timer_sync(&info->se_info.se_active_timer); |
---|
424 | 445 | |
---|
| 446 | + cancel_work_sync(&info->se_info.timeout_work); |
---|
425 | 447 | info->se_info.bwi_active = false; |
---|
426 | 448 | info->se_info.se_active = false; |
---|
427 | 449 | } |
---|