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