1 /******************************************************************************
2 *
3 * Copyright (C) 2010-2014 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains the implementation for Type 4 tag in Card Emulation
22 * mode.
23 *
24 ******************************************************************************/
25 #include <log/log.h>
26 #include <string.h>
27
28 #include <android-base/stringprintf.h>
29 #include <base/logging.h>
30
31 #include "nfc_target.h"
32
33 #include "bt_types.h"
34 #include "ce_api.h"
35 #include "ce_int.h"
36 #include "nfc_int.h"
37 #include "tags_int.h"
38
39 using android::base::StringPrintf;
40
41 extern bool nfc_debug_enabled;
42
43 #if (CE_TEST_INCLUDED == TRUE) /* test only */
44 bool mapping_aid_test_enabled = false;
45 uint8_t ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN] = {0xD2, 0x76, 0x00, 0x00,
46 0x85, 0x01, 0x01};
47 #endif
48
49 /*******************************************************************************
50 **
51 ** Function ce_t4t_send_to_lower
52 **
53 ** Description Send packet to lower layer
54 **
55 ** Returns TRUE if success
56 **
57 *******************************************************************************/
ce_t4t_send_to_lower(NFC_HDR * p_r_apdu)58 static bool ce_t4t_send_to_lower(NFC_HDR* p_r_apdu) {
59 if (NFC_SendData(NFC_RF_CONN_ID, p_r_apdu) != NFC_STATUS_OK) {
60 LOG(ERROR) << StringPrintf("failed");
61 return false;
62 }
63 return true;
64 }
65
66 /*******************************************************************************
67 **
68 ** Function ce_t4t_send_status
69 **
70 ** Description Send status on R-APDU to peer
71 **
72 ** Returns TRUE if success
73 **
74 *******************************************************************************/
ce_t4t_send_status(uint16_t status)75 static bool ce_t4t_send_status(uint16_t status) {
76 NFC_HDR* p_r_apdu;
77 uint8_t* p;
78
79 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Status:0x%04X", status);
80
81 p_r_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_CE_POOL_ID);
82
83 if (!p_r_apdu) {
84 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
85 return false;
86 }
87
88 p_r_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
89 p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
90
91 UINT16_TO_BE_STREAM(p, status);
92
93 p_r_apdu->len = T4T_RSP_STATUS_WORDS_SIZE;
94
95 if (!ce_t4t_send_to_lower(p_r_apdu)) {
96 return false;
97 }
98 return true;
99 }
100
101 /*******************************************************************************
102 **
103 ** Function ce_t4t_select_file
104 **
105 ** Description Select a file
106 **
107 ** Returns TRUE if success
108 **
109 *******************************************************************************/
ce_t4t_select_file(uint16_t file_id)110 static bool ce_t4t_select_file(uint16_t file_id) {
111 tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
112
113 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("FileID:0x%04X", file_id);
114
115 if (file_id == T4T_CC_FILE_ID) {
116 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Select CC file");
117
118 p_t4t->status |= CE_T4T_STATUS_CC_FILE_SELECTED;
119 p_t4t->status &= ~(CE_T4T_STATUS_NDEF_SELECTED);
120
121 return true;
122 }
123
124 if (file_id == CE_T4T_MANDATORY_NDEF_FILE_ID) {
125 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
126 "NLEN:0x%04X, MaxFileSize:0x%04X, "
127 "WriteAccess:%s",
128 p_t4t->nlen, p_t4t->max_file_size,
129 (p_t4t->status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY ? "RW" : "RO"));
130
131 p_t4t->status |= CE_T4T_STATUS_NDEF_SELECTED;
132 p_t4t->status &= ~(CE_T4T_STATUS_CC_FILE_SELECTED);
133
134 return true;
135 } else {
136 LOG(ERROR) << StringPrintf("Cannot find file ID (0x%04X)", file_id);
137
138 p_t4t->status &= ~(CE_T4T_STATUS_CC_FILE_SELECTED);
139 p_t4t->status &= ~(CE_T4T_STATUS_NDEF_SELECTED);
140
141 return false;
142 }
143 }
144
145 /*******************************************************************************
146 **
147 ** Function ce_t4t_read_binary
148 **
149 ** Description Read data from selected file and send R-APDU to peer
150 **
151 ** Returns TRUE if success
152 **
153 *******************************************************************************/
ce_t4t_read_binary(uint16_t offset,uint8_t length)154 static bool ce_t4t_read_binary(uint16_t offset, uint8_t length) {
155 tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
156 uint8_t *p_src = nullptr, *p_dst;
157 NFC_HDR* p_r_apdu;
158
159 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
160 "Offset:0x%04X, Length:0x%04X, selected status = "
161 "0x%02X",
162 offset, length, p_t4t->status);
163
164 if (p_t4t->status & CE_T4T_STATUS_CC_FILE_SELECTED) {
165 p_src = p_t4t->cc_file;
166 } else if (p_t4t->status & CE_T4T_STATUS_NDEF_SELECTED) {
167 if (p_t4t->p_scratch_buf)
168 p_src = p_t4t->p_scratch_buf;
169 else
170 p_src = p_t4t->p_ndef_msg;
171 }
172
173 if (p_src) {
174 p_r_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_CE_POOL_ID);
175
176 if (!p_r_apdu) {
177 LOG(ERROR) << StringPrintf("Cannot allocate buffer");
178 return false;
179 }
180
181 p_r_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
182 p_dst = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
183
184 p_r_apdu->len = length;
185
186 /* add NLEN before NDEF message and adjust offset */
187 /* if NDEF file is selected and offset < T4T_FILE_LENGTH_SIZE */
188 if ((p_t4t->status & CE_T4T_STATUS_NDEF_SELECTED) && (length > 0)) {
189 if (offset == 0) {
190 UINT16_TO_BE_STREAM(p_dst, p_t4t->nlen);
191
192 if (length == 1) {
193 length = 0;
194 p_dst--;
195 } else /* length >= 2 */
196 length -= T4T_FILE_LENGTH_SIZE;
197 } else if (offset == 1) {
198 UINT8_TO_BE_STREAM(p_dst, (uint8_t)(p_t4t->nlen));
199
200 offset = 0;
201 length--;
202 } else {
203 offset -= T4T_FILE_LENGTH_SIZE;
204 }
205 }
206
207 if (length > 0) {
208 memcpy(p_dst, p_src + offset, length);
209 p_dst += length;
210 }
211
212 UINT16_TO_BE_STREAM(p_dst, T4T_RSP_CMD_CMPLTED);
213 p_r_apdu->len += T4T_RSP_STATUS_WORDS_SIZE;
214
215 if (!ce_t4t_send_to_lower(p_r_apdu)) {
216 return false;
217 }
218 return true;
219 } else {
220 LOG(ERROR) << StringPrintf("No selected file");
221
222 if (!ce_t4t_send_status(T4T_RSP_CMD_NOT_ALLOWED)) {
223 return false;
224 }
225 return true;
226 }
227 }
228
229 /*******************************************************************************
230 **
231 ** Function ce_t4t_update_binary
232 **
233 ** Description Update file and send R-APDU to peer
234 **
235 ** Returns TRUE if success
236 **
237 *******************************************************************************/
ce_t4t_update_binary(uint16_t offset,uint8_t length,uint8_t * p_data)238 static bool ce_t4t_update_binary(uint16_t offset, uint8_t length,
239 uint8_t* p_data) {
240 tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
241 uint8_t* p;
242 uint8_t file_length[2];
243 uint16_t starting_offset;
244 tCE_DATA ce_data;
245
246 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
247 "Offset:0x%04X, Length:0x%04X, selected status "
248 "= 0x%02X",
249 offset, length, p_t4t->status);
250
251 starting_offset = offset;
252
253 /* update file size (NLEN) */
254 if ((offset < T4T_FILE_LENGTH_SIZE) && (length > 0)) {
255 p = file_length;
256 UINT16_TO_BE_STREAM(p, p_t4t->nlen);
257
258 while ((offset < T4T_FILE_LENGTH_SIZE) && (length > 0)) {
259 *(file_length + offset++) = *(p_data++);
260 length--;
261 }
262
263 p = file_length;
264 BE_STREAM_TO_UINT16(p_t4t->nlen, p);
265 }
266
267 if (length > 0)
268 memcpy(p_t4t->p_scratch_buf + offset - T4T_FILE_LENGTH_SIZE, p_data,
269 length);
270
271 /* if this is the last step: writing non-zero length in NLEN */
272 if ((starting_offset == 0) && (p_t4t->nlen > 0)) {
273 nfc_stop_quick_timer(&p_t4t->timer);
274
275 if (ce_cb.p_cback) {
276 ce_data.update_info.status = NFC_STATUS_OK;
277 ce_data.update_info.length = p_t4t->nlen;
278 ce_data.update_info.p_data = p_t4t->p_scratch_buf;
279
280 (*ce_cb.p_cback)(CE_T4T_NDEF_UPDATE_CPLT_EVT, &ce_data);
281 DLOG_IF(INFO, nfc_debug_enabled)
282 << StringPrintf("Sent CE_T4T_NDEF_UPDATE_CPLT_EVT");
283 }
284
285 p_t4t->status &= ~(CE_T4T_STATUS_NDEF_FILE_UPDATING);
286 } else if (!(p_t4t->status & CE_T4T_STATUS_NDEF_FILE_UPDATING)) {
287 /* starting of updating */
288 p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_UPDATING;
289
290 nfc_start_quick_timer(
291 &p_t4t->timer, NFC_TTYPE_CE_T4T_UPDATE,
292 (CE_T4T_TOUT_UPDATE * QUICK_TIMER_TICKS_PER_SEC) / 1000);
293
294 if (ce_cb.p_cback) (*ce_cb.p_cback)(CE_T4T_NDEF_UPDATE_START_EVT, nullptr);
295 }
296
297 if (!ce_t4t_send_status(T4T_RSP_CMD_CMPLTED)) {
298 return false;
299 } else {
300 return true;
301 }
302 }
303
304 /*******************************************************************************
305 **
306 ** Function ce_t4t_set_version_in_cc
307 **
308 ** Description update version in CC file
309 ** If reader selects NDEF Tag Application with V1.0 AID then
310 ** set V1.0 into CC file.
311 ** If reader selects NDEF Tag Application with V2.0 AID then
312 ** set V2.0 into CC file.
313 **
314 ** Returns None
315 **
316 *******************************************************************************/
ce_t4t_set_version_in_cc(uint8_t version)317 static void ce_t4t_set_version_in_cc(uint8_t version) {
318 tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
319 uint8_t* p;
320
321 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("version = 0x%02X", version);
322
323 p = p_t4t->cc_file + T4T_VERSION_OFFSET_IN_CC;
324
325 UINT8_TO_BE_STREAM(p, version);
326 }
327
328 /*******************************************************************************
329 **
330 ** Function ce_t4t_process_select_file_cmd
331 **
332 ** Description This function processes Select Command by file ID.
333 **
334 ** Returns TRUE if success
335 **
336 *******************************************************************************/
ce_t4t_process_select_file_cmd(uint8_t * p_cmd)337 static bool ce_t4t_process_select_file_cmd(uint8_t* p_cmd) {
338 uint8_t data_len;
339 uint16_t file_id, status_words;
340
341 DLOG_IF(INFO, nfc_debug_enabled) << __func__;
342
343 p_cmd++; /* skip P2 */
344
345 /* Lc Byte */
346 BE_STREAM_TO_UINT8(data_len, p_cmd);
347
348 if (data_len == T4T_FILE_ID_SIZE) {
349 /* File ID */
350 BE_STREAM_TO_UINT16(file_id, p_cmd);
351
352 if (ce_t4t_select_file(file_id)) {
353 status_words = T4T_RSP_CMD_CMPLTED;
354 } else {
355 status_words = T4T_RSP_NOT_FOUND;
356 }
357 } else {
358 status_words = T4T_RSP_WRONG_LENGTH;
359 }
360
361 if (!ce_t4t_send_status(status_words)) {
362 return false;
363 }
364
365 if (status_words == T4T_RSP_CMD_CMPLTED) {
366 return true;
367 }
368 return false;
369 }
370
371 /*******************************************************************************
372 **
373 ** Function ce_t4t_process_select_app_cmd
374 **
375 ** Description This function processes Select Command by AID.
376 **
377 ** Returns none
378 **
379 *******************************************************************************/
ce_t4t_process_select_app_cmd(uint8_t * p_cmd,NFC_HDR * p_c_apdu)380 static void ce_t4t_process_select_app_cmd(uint8_t* p_cmd, NFC_HDR* p_c_apdu) {
381 uint8_t data_len;
382 uint16_t status_words = 0x0000; /* invalid status words */
383 tCE_DATA ce_data;
384 uint8_t xx;
385
386 DLOG_IF(INFO, nfc_debug_enabled) << __func__;
387
388 p_cmd++; /* skip P2 */
389
390 /* Lc Byte */
391 BE_STREAM_TO_UINT8(data_len, p_cmd);
392
393 /*CLS+INS+P1+P2+Lc+Data*/
394 if (data_len > (p_c_apdu->len - T4T_CMD_MAX_HDR_SIZE)) {
395 LOG(ERROR) << StringPrintf("Wrong length in ce_t4t_process_select_app_cmd");
396 android_errorWriteLog(0x534e4554, "115635871");
397 ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
398 GKI_freebuf(p_c_apdu);
399 return;
400 }
401 #if (CE_TEST_INCLUDED == TRUE)
402 if (mapping_aid_test_enabled) {
403 if ((data_len == T4T_V20_NDEF_TAG_AID_LEN) &&
404 (!memcmp(p_cmd, ce_test_tag_app_id, data_len)) &&
405 (ce_cb.mem.t4t.p_ndef_msg)) {
406 GKI_freebuf(p_c_apdu);
407 ce_t4t_send_status((uint16_t)T4T_RSP_CMD_CMPLTED);
408 return;
409 }
410 }
411 #endif
412
413 /*
414 ** Compare AIDs registered by applications
415 ** if found, use callback of the application
416 ** otherwise, return error and maintain the same status
417 */
418 ce_cb.mem.t4t.selected_aid_idx = CE_T4T_MAX_REG_AID;
419 for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) {
420 if ((ce_cb.mem.t4t.reg_aid[xx].aid_len > 0) &&
421 (ce_cb.mem.t4t.reg_aid[xx].aid_len == data_len) &&
422 (!(memcmp(ce_cb.mem.t4t.reg_aid[xx].aid, p_cmd, data_len)))) {
423 ce_cb.mem.t4t.selected_aid_idx = xx;
424 break;
425 }
426 }
427
428 /* if found matched AID */
429 if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID) {
430 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_CC_FILE_SELECTED);
431 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_NDEF_SELECTED);
432 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_T4T_APP_SELECTED);
433 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_WILDCARD_AID_SELECTED);
434 ce_cb.mem.t4t.status |= CE_T4T_STATUS_REG_AID_SELECTED;
435
436 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
437 "Registered AID[%02X%02X%02X%02X...] "
438 "is selected",
439 ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[0],
440 ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[1],
441 ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[2],
442 ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[3]);
443
444 ce_data.raw_frame.status = NFC_STATUS_OK;
445 ce_data.raw_frame.p_data = p_c_apdu;
446 ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx;
447
448 p_c_apdu = nullptr;
449
450 (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback))(
451 CE_T4T_RAW_FRAME_EVT, &ce_data);
452 } else if ((data_len == T4T_V20_NDEF_TAG_AID_LEN) &&
453 (!memcmp(p_cmd, t4t_v20_ndef_tag_aid, data_len - 1)) &&
454 (ce_cb.mem.t4t.p_ndef_msg)) {
455 p_cmd += data_len - 1;
456
457 /* adjust version if possible */
458 if ((*p_cmd) == 0x00) {
459 ce_t4t_set_version_in_cc(T4T_VERSION_1_0);
460 status_words = T4T_RSP_CMD_CMPLTED;
461 } else if ((*p_cmd) == 0x01) {
462 ce_t4t_set_version_in_cc(T4T_VERSION_2_0);
463 status_words = T4T_RSP_CMD_CMPLTED;
464 } else {
465 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Not found matched AID");
466 status_words = T4T_RSP_NOT_FOUND;
467 }
468 } else if (ce_cb.mem.t4t.p_wildcard_aid_cback) {
469 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_CC_FILE_SELECTED);
470 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_NDEF_SELECTED);
471 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_T4T_APP_SELECTED);
472 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_REG_AID_SELECTED);
473 ce_cb.mem.t4t.status |= CE_T4T_STATUS_WILDCARD_AID_SELECTED;
474
475 ce_data.raw_frame.status = NFC_STATUS_OK;
476 ce_data.raw_frame.p_data = p_c_apdu;
477 ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE;
478 p_c_apdu = nullptr;
479
480 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
481 "CET4T: Forward raw frame (SELECT APP) to wildcard AID handler");
482 (*(ce_cb.mem.t4t.p_wildcard_aid_cback))(CE_T4T_RAW_FRAME_EVT, &ce_data);
483 } else {
484 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
485 "Not found matched AID or not "
486 "listening T4T NDEF");
487 status_words = T4T_RSP_NOT_FOUND;
488 }
489
490 if (status_words) {
491 /* if T4T CE can support */
492 if (status_words == T4T_RSP_CMD_CMPLTED) {
493 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_CC_FILE_SELECTED);
494 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_NDEF_SELECTED);
495 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_REG_AID_SELECTED);
496 ce_cb.mem.t4t.status &= ~(CE_T4T_STATUS_WILDCARD_AID_SELECTED);
497 ce_cb.mem.t4t.status |= CE_T4T_STATUS_T4T_APP_SELECTED;
498
499 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("T4T CE App selected");
500 }
501
502 ce_t4t_send_status(status_words);
503 GKI_freebuf(p_c_apdu);
504 }
505 /* if status_words is not set then upper layer will send R-APDU */
506
507 return;
508 }
509
510 /*******************************************************************************
511 **
512 ** Function ce_t4t_process_timeout
513 **
514 ** Description process timeout event
515 **
516 ** Returns none
517 **
518 *******************************************************************************/
ce_t4t_process_timeout(TIMER_LIST_ENT * p_tle)519 void ce_t4t_process_timeout(TIMER_LIST_ENT* p_tle) {
520 tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
521 tCE_DATA ce_data;
522
523 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("event=%d", p_tle->event);
524
525 if (p_tle->event == NFC_TTYPE_CE_T4T_UPDATE) {
526 if (p_t4t->status & CE_T4T_STATUS_NDEF_FILE_UPDATING) {
527 ce_data.status = NFC_STATUS_TIMEOUT;
528
529 if (ce_cb.p_cback)
530 (*ce_cb.p_cback)(CE_T4T_NDEF_UPDATE_ABORT_EVT, &ce_data);
531
532 p_t4t->status &= ~(CE_T4T_STATUS_NDEF_FILE_UPDATING);
533 }
534 } else {
535 LOG(ERROR) << StringPrintf("unknown event=%d", p_tle->event);
536 }
537 }
538
539 /*******************************************************************************
540 **
541 ** Function ce_t4t_data_cback
542 **
543 ** Description This callback function receives the data from NFCC.
544 **
545 ** Returns none
546 **
547 *******************************************************************************/
ce_t4t_data_cback(uint8_t conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)548 static void ce_t4t_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
549 tNFC_CONN* p_data) {
550 NFC_HDR* p_c_apdu;
551 uint8_t* p_cmd;
552 uint8_t cla = 0, instruct = 0, select_type = 0, length = 0;
553 uint16_t offset, max_file_size;
554 tCE_DATA ce_data;
555
556 if (event == NFC_DEACTIVATE_CEVT) {
557 NFC_SetStaticRfCback(nullptr);
558 return;
559 }
560 if (event != NFC_DATA_CEVT) {
561 return;
562 }
563
564 p_c_apdu = (NFC_HDR*)p_data->data.p_data;
565 if (!p_c_apdu) {
566 LOG(ERROR) << StringPrintf("Invalid p_c_apdu");
567 return;
568 }
569
570 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("conn_id = 0x%02X", conn_id);
571
572 p_cmd = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
573
574 if (p_c_apdu->len == 0) {
575 LOG(ERROR) << StringPrintf("Wrong length in ce_t4t_data_cback");
576 android_errorWriteLog(0x534e4554, "115635871");
577 ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
578 GKI_freebuf(p_c_apdu);
579 return;
580 }
581
582 /* Class Byte */
583 BE_STREAM_TO_UINT8(cla, p_cmd);
584
585 /* Don't check class if registered AID has been selected */
586 if ((cla != T4T_CMD_CLASS) &&
587 ((ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) == 0) &&
588 ((ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) == 0)) {
589 GKI_freebuf(p_c_apdu);
590 ce_t4t_send_status(T4T_RSP_CLASS_NOT_SUPPORTED);
591 return;
592 }
593
594 /*CLA+INS+P1+P2 = 4 bytes*/
595 if (p_c_apdu->len >= T4T_CMD_MIN_HDR_SIZE) {
596 /* Instruction Byte */
597 BE_STREAM_TO_UINT8(instruct, p_cmd);
598
599 if ((cla == T4T_CMD_CLASS) && (instruct == T4T_CMD_INS_SELECT)) {
600 /* P1 Byte */
601 BE_STREAM_TO_UINT8(select_type, p_cmd);
602
603 if (select_type == T4T_CMD_P1_SELECT_BY_NAME) {
604 /*CLA+INS+P1+P2+Lc = 5 bytes*/
605 if (p_c_apdu->len >= T4T_CMD_MAX_HDR_SIZE) {
606 ce_t4t_process_select_app_cmd(p_cmd, p_c_apdu);
607 return;
608 } else {
609 LOG(ERROR) << StringPrintf("Wrong length in select app cmd");
610 android_errorWriteLog(0x534e4554, "115635871");
611 ce_t4t_send_status(T4T_RSP_NOT_FOUND);
612 GKI_freebuf(p_c_apdu);
613 return;
614 }
615 }
616 }
617 }
618
619 /* if registered AID is selected */
620 if (ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) {
621 DLOG_IF(INFO, nfc_debug_enabled)
622 << StringPrintf("CET4T: Forward raw frame to registered AID");
623
624 /* forward raw frame to upper layer */
625 if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID) {
626 ce_data.raw_frame.status = p_data->data.status;
627 ce_data.raw_frame.p_data = p_c_apdu;
628 ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx;
629 p_c_apdu = nullptr;
630
631 (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback))(
632 CE_T4T_RAW_FRAME_EVT, &ce_data);
633 } else {
634 GKI_freebuf(p_c_apdu);
635 ce_t4t_send_status(T4T_RSP_NOT_FOUND);
636 return;
637 }
638 } else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) {
639 DLOG_IF(INFO, nfc_debug_enabled)
640 << StringPrintf("CET4T: Forward raw frame to wildcard AID handler");
641
642 /* forward raw frame to upper layer */
643 ce_data.raw_frame.status = p_data->data.status;
644 ce_data.raw_frame.p_data = p_c_apdu;
645 ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE;
646 p_c_apdu = nullptr;
647
648 (*(ce_cb.mem.t4t.p_wildcard_aid_cback))(CE_T4T_RAW_FRAME_EVT, &ce_data);
649 } else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_T4T_APP_SELECTED) {
650 if (instruct == T4T_CMD_INS_SELECT) {
651 /* P1 Byte is already parsed */
652 if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID) {
653 /* CLA+INS+P1+P2+Lc+FILE_ID = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE */
654 if (p_c_apdu->len < (T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE)) {
655 LOG(ERROR) << "Wrong length";
656 GKI_freebuf(p_c_apdu);
657 ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
658 return;
659 }
660 ce_t4t_process_select_file_cmd(p_cmd);
661 } else {
662 LOG(ERROR) << StringPrintf("CET4T: Bad P1 byte (0x%02X)", select_type);
663 ce_t4t_send_status(T4T_RSP_WRONG_PARAMS);
664 }
665 } else if (instruct == T4T_CMD_INS_READ_BINARY) {
666 if ((ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) ||
667 (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED)) {
668 if (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) {
669 max_file_size = T4T_FC_TLV_OFFSET_IN_CC + T4T_FILE_CONTROL_TLV_SIZE;
670 } else {
671 max_file_size = ce_cb.mem.t4t.max_file_size;
672 }
673
674 /*CLA+INS+Offset(P1P2)+Le = 5 bytes*/
675 if (p_c_apdu->len < T4T_CMD_MAX_HDR_SIZE) {
676 LOG(ERROR) << "Wrong length";
677 android_errorWriteLog(0x534e4554, "120845341");
678 GKI_freebuf(p_c_apdu);
679 ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
680 return;
681 }
682 BE_STREAM_TO_UINT16(offset, p_cmd); /* Offset */
683 BE_STREAM_TO_UINT8(length, p_cmd); /* Le */
684
685 /* check if valid parameters */
686 if ((uint32_t)length <= CE_T4T_MAX_LE) {
687 /* CE allows to read more than current file size but not max file size
688 */
689 if (length + offset > max_file_size) {
690 if (offset < max_file_size) {
691 length = (uint8_t)(max_file_size - offset);
692
693 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
694 "CET4T: length is reduced to %d by max_file_size (%d)",
695 length, max_file_size);
696 } else {
697 LOG(ERROR) << StringPrintf(
698 "CET4T: offset (%d) must be less than max_file_size (%d)",
699 offset, max_file_size);
700 length = 0;
701 }
702 }
703 } else {
704 LOG(ERROR) << StringPrintf(
705 "CET4T: length (%d) must be less than MLe (%zu)", length,
706 CE_T4T_MAX_LE);
707 length = 0;
708 }
709
710 if (length > 0)
711 ce_t4t_read_binary(offset, length);
712 else
713 ce_t4t_send_status(T4T_RSP_WRONG_PARAMS);
714 } else {
715 LOG(ERROR) << StringPrintf("CET4T: File has not been selected");
716 ce_t4t_send_status(T4T_RSP_CMD_NOT_ALLOWED);
717 }
718 } else if (instruct == T4T_CMD_INS_UPDATE_BINARY) {
719 if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY) {
720 LOG(ERROR) << StringPrintf("CET4T: No access right");
721 ce_t4t_send_status(T4T_RSP_CMD_NOT_ALLOWED);
722 } else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED) {
723 /*CLA+INS+Offset(P1P2)+Lc = 5 bytes*/
724 if (p_c_apdu->len < T4T_CMD_MAX_HDR_SIZE) {
725 LOG(ERROR) << "Wrong length";
726 android_errorWriteLog(0x534e4554, "120845341");
727 GKI_freebuf(p_c_apdu);
728 ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
729 return;
730 }
731 BE_STREAM_TO_UINT16(offset, p_cmd); /* Offset */
732 BE_STREAM_TO_UINT8(length, p_cmd); /* Lc */
733
734 /* check if valid parameters */
735 if ((uint32_t)length <= CE_T4T_MAX_LC &&
736 /* check if data fits into the apdu */
737 (uint16_t)length <= p_c_apdu->len - T4T_CMD_MAX_HDR_SIZE) {
738 if (length + offset > ce_cb.mem.t4t.max_file_size) {
739 LOG(ERROR) << StringPrintf(
740 "CET4T: length (%d) + offset (%d) must be less than "
741 "max_file_size (%d)",
742 length, offset, ce_cb.mem.t4t.max_file_size);
743 length = 0;
744 }
745 } else {
746 LOG(ERROR) << StringPrintf(
747 "CET4T: length (%d) must be less than MLc (%zu)", length,
748 CE_T4T_MAX_LC);
749 android_errorWriteLog(0x534e4554, "157649298");
750 length = 0;
751 }
752
753 if (length > 0)
754 ce_t4t_update_binary(offset, length, p_cmd);
755 else
756 ce_t4t_send_status(T4T_RSP_WRONG_PARAMS);
757 } else {
758 LOG(ERROR) << StringPrintf("CET4T: NDEF File has not been selected");
759 ce_t4t_send_status(T4T_RSP_CMD_NOT_ALLOWED);
760 }
761 } else {
762 LOG(ERROR) << StringPrintf("CET4T: Unsupported Instruction byte (0x%02X)",
763 instruct);
764 ce_t4t_send_status(T4T_RSP_INSTR_NOT_SUPPORTED);
765 }
766 } else {
767 LOG(ERROR) << StringPrintf("CET4T: Application has not been selected");
768 ce_t4t_send_status(T4T_RSP_CMD_NOT_ALLOWED);
769 }
770
771 if (p_c_apdu) GKI_freebuf(p_c_apdu);
772 }
773
774 /*******************************************************************************
775 **
776 ** Function ce_select_t4t
777 **
778 ** Description Select Type 4 Tag
779 **
780 ** Returns NFC_STATUS_OK if success
781 **
782 *******************************************************************************/
ce_select_t4t(void)783 tNFC_STATUS ce_select_t4t(void) {
784 tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
785
786 DLOG_IF(INFO, nfc_debug_enabled) << __func__;
787
788 nfc_stop_quick_timer(&p_t4t->timer);
789
790 /* clear other than read-only flag */
791 p_t4t->status &= CE_T4T_STATUS_NDEF_FILE_READ_ONLY;
792
793 NFC_SetStaticRfCback(ce_t4t_data_cback);
794
795 return NFC_STATUS_OK;
796 }
797
798 /*******************************************************************************
799 **
800 ** Function CE_T4tSetLocalNDEFMsg
801 **
802 ** Description Initialise CE Type 4 Tag with mandatory NDEF message
803 **
804 ** The following event may be returned
805 ** CE_T4T_UPDATE_START_EVT for starting update
806 ** CE_T4T_UPDATE_CPLT_EVT for complete update
807 ** CE_T4T_UPDATE_ABORT_EVT for failure of update
808 ** CE_T4T_RAW_FRAME_EVT for raw frame
809 **
810 ** read_only: TRUE if read only
811 ** ndef_msg_max: Max NDEF message size
812 ** ndef_msg_len: NDEF message size
813 ** p_ndef_msg: NDEF message (excluding NLEN)
814 ** p_scratch_buf: temp storage for update
815 **
816 ** Returns NFC_STATUS_OK if success
817 **
818 *******************************************************************************/
CE_T4tSetLocalNDEFMsg(bool read_only,uint16_t ndef_msg_max,uint16_t ndef_msg_len,uint8_t * p_ndef_msg,uint8_t * p_scratch_buf)819 tNFC_STATUS CE_T4tSetLocalNDEFMsg(bool read_only, uint16_t ndef_msg_max,
820 uint16_t ndef_msg_len, uint8_t* p_ndef_msg,
821 uint8_t* p_scratch_buf) {
822 tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
823 uint8_t* p;
824
825 DLOG_IF(INFO, nfc_debug_enabled)
826 << StringPrintf("read_only=%d, ndef_msg_max=%d, ndef_msg_len=%d",
827 read_only, ndef_msg_max, ndef_msg_len);
828
829 if (!p_ndef_msg) {
830 p_t4t->p_ndef_msg = nullptr;
831
832 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("T4T is disabled");
833 return NFC_STATUS_OK;
834 }
835
836 if ((!read_only) && (!p_scratch_buf)) {
837 LOG(ERROR) << StringPrintf(
838 "p_scratch_buf cannot be NULL if not "
839 "read-only");
840 return NFC_STATUS_FAILED;
841 }
842
843 #if (CE_TEST_INCLUDED == TRUE)
844 mapping_aid_test_enabled = false;
845 #endif
846
847 /* Initialise CC file */
848 p = p_t4t->cc_file;
849
850 UINT16_TO_BE_STREAM(p, T4T_CC_FILE_MIN_LEN);
851 UINT8_TO_BE_STREAM(p, T4T_MY_VERSION);
852 UINT16_TO_BE_STREAM(p, CE_T4T_MAX_LE);
853 UINT16_TO_BE_STREAM(p, CE_T4T_MAX_LC);
854
855 /* Mandatory NDEF File Control TLV */
856 UINT8_TO_BE_STREAM(p, T4T_NDEF_FILE_CONTROL_TYPE); /* type */
857 UINT8_TO_BE_STREAM(p, T4T_FILE_CONTROL_LENGTH); /* length */
858 UINT16_TO_BE_STREAM(p, CE_T4T_MANDATORY_NDEF_FILE_ID); /* file ID */
859 UINT16_TO_BE_STREAM(
860 p, ndef_msg_max + T4T_FILE_LENGTH_SIZE); /* max NDEF file size */
861 UINT8_TO_BE_STREAM(p, T4T_FC_READ_ACCESS); /* read access */
862
863 if (read_only) {
864 UINT8_TO_BE_STREAM(p, T4T_FC_NO_WRITE_ACCESS); /* read only */
865 p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_READ_ONLY;
866 } else {
867 UINT8_TO_BE_STREAM(p, T4T_FC_WRITE_ACCESS); /* write access */
868 p_t4t->status &= ~(CE_T4T_STATUS_NDEF_FILE_READ_ONLY);
869 }
870
871 /* set mandatory NDEF file */
872 p_t4t->p_ndef_msg = p_ndef_msg;
873 p_t4t->nlen = ndef_msg_len;
874 p_t4t->max_file_size = ndef_msg_max + T4T_FILE_LENGTH_SIZE;
875
876 /* Initialize scratch buffer */
877 p_t4t->p_scratch_buf = p_scratch_buf;
878
879 if (p_scratch_buf) {
880 memcpy(p_scratch_buf, p_ndef_msg, ndef_msg_len);
881 }
882
883 return NFC_STATUS_OK;
884 }
885
886 /*******************************************************************************
887 **
888 ** Function CE_T4tRegisterAID
889 **
890 ** Description Register AID in CE T4T
891 **
892 ** aid_len: length of AID (up to NFC_MAX_AID_LEN)
893 ** p_aid: AID
894 ** p_cback: Raw frame will be forwarded with CE_RAW_FRAME_EVT
895 **
896 ** Returns tCE_T4T_AID_HANDLE if successful,
897 ** CE_T4T_AID_HANDLE_INVALID otherwisse
898 **
899 *******************************************************************************/
CE_T4tRegisterAID(uint8_t aid_len,uint8_t * p_aid,tCE_CBACK * p_cback)900 tCE_T4T_AID_HANDLE CE_T4tRegisterAID(uint8_t aid_len, uint8_t* p_aid,
901 tCE_CBACK* p_cback) {
902 tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
903 uint8_t xx;
904
905 /* Handle registering callback for wildcard AID (all AIDs) */
906 if (aid_len == 0) {
907 DLOG_IF(INFO, nfc_debug_enabled)
908 << StringPrintf("registering callback for wildcard AID ");
909
910 /* Check if a wildcard callback is already registered (only one is allowed)
911 */
912 if (p_t4t->p_wildcard_aid_cback != nullptr) {
913 LOG(ERROR) << StringPrintf(
914 "only one wildcard AID can be registered at "
915 "time.");
916 return CE_T4T_AID_HANDLE_INVALID;
917 }
918
919 DLOG_IF(INFO, nfc_debug_enabled)
920 << StringPrintf("handle 0x%02x registered (for wildcard AID)",
921 CE_T4T_WILDCARD_AID_HANDLE);
922 p_t4t->p_wildcard_aid_cback = p_cback;
923 return CE_T4T_WILDCARD_AID_HANDLE;
924 }
925
926 DLOG_IF(INFO, nfc_debug_enabled)
927 << StringPrintf("AID [%02X%02X%02X%02X...], %d bytes", *p_aid,
928 *(p_aid + 1), *(p_aid + 2), *(p_aid + 3), aid_len);
929
930 if (aid_len > NFC_MAX_AID_LEN) {
931 LOG(ERROR) << StringPrintf("AID is up to %d bytes", NFC_MAX_AID_LEN);
932 return CE_T4T_AID_HANDLE_INVALID;
933 }
934
935 if (p_cback == nullptr) {
936 LOG(ERROR) << StringPrintf("callback must be provided");
937 return CE_T4T_AID_HANDLE_INVALID;
938 }
939
940 for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) {
941 if ((p_t4t->reg_aid[xx].aid_len == aid_len) &&
942 (!(memcmp(p_t4t->reg_aid[xx].aid, p_aid, aid_len)))) {
943 LOG(ERROR) << StringPrintf("already registered");
944 return CE_T4T_AID_HANDLE_INVALID;
945 }
946 }
947
948 for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) {
949 if (p_t4t->reg_aid[xx].aid_len == 0) {
950 p_t4t->reg_aid[xx].aid_len = aid_len;
951 p_t4t->reg_aid[xx].p_cback = p_cback;
952 memcpy(p_t4t->reg_aid[xx].aid, p_aid, aid_len);
953 break;
954 }
955 }
956
957 if (xx >= CE_T4T_MAX_REG_AID) {
958 LOG(ERROR) << StringPrintf("No resource");
959 return CE_T4T_AID_HANDLE_INVALID;
960 } else {
961 DLOG_IF(INFO, nfc_debug_enabled)
962 << StringPrintf("handle 0x%02x registered", xx);
963 }
964
965 return (xx);
966 }
967
968 /*******************************************************************************
969 **
970 ** Function CE_T4tDeregisterAID
971 **
972 ** Description Deregister AID in CE T4T
973 **
974 ** Returns NFC_STATUS_OK if success
975 **
976 *******************************************************************************/
CE_T4tDeregisterAID(tCE_T4T_AID_HANDLE aid_handle)977 extern void CE_T4tDeregisterAID(tCE_T4T_AID_HANDLE aid_handle) {
978 tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
979
980 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("handle 0x%02x", aid_handle);
981
982 /* Check if deregistering wildcard AID */
983 if (aid_handle == CE_T4T_WILDCARD_AID_HANDLE) {
984 if (p_t4t->p_wildcard_aid_cback != nullptr) {
985 p_t4t->p_wildcard_aid_cback = nullptr;
986 } else {
987 LOG(ERROR) << StringPrintf("Invalid handle");
988 }
989 return;
990 }
991
992 /* Deregister AID */
993 if ((aid_handle >= CE_T4T_MAX_REG_AID) ||
994 (p_t4t->reg_aid[aid_handle].aid_len == 0)) {
995 LOG(ERROR) << StringPrintf("Invalid handle");
996 } else {
997 p_t4t->reg_aid[aid_handle].aid_len = 0;
998 p_t4t->reg_aid[aid_handle].p_cback = nullptr;
999 }
1000 }
1001