• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     }
637   } else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) {
638     DLOG_IF(INFO, nfc_debug_enabled)
639         << StringPrintf("CET4T: Forward raw frame to wildcard AID handler");
640 
641     /* forward raw frame to upper layer */
642     ce_data.raw_frame.status = p_data->data.status;
643     ce_data.raw_frame.p_data = p_c_apdu;
644     ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE;
645     p_c_apdu = nullptr;
646 
647     (*(ce_cb.mem.t4t.p_wildcard_aid_cback))(CE_T4T_RAW_FRAME_EVT, &ce_data);
648   } else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_T4T_APP_SELECTED) {
649     if (instruct == T4T_CMD_INS_SELECT) {
650       /* P1 Byte is already parsed */
651       if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID) {
652         /* CLA+INS+P1+P2+Lc+FILE_ID = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE */
653         if (p_c_apdu->len < (T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE)) {
654           LOG(ERROR) << "Wrong length";
655           GKI_freebuf(p_c_apdu);
656           ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
657           return;
658         }
659         ce_t4t_process_select_file_cmd(p_cmd);
660       } else {
661         LOG(ERROR) << StringPrintf("CET4T: Bad P1 byte (0x%02X)", select_type);
662         ce_t4t_send_status(T4T_RSP_WRONG_PARAMS);
663       }
664     } else if (instruct == T4T_CMD_INS_READ_BINARY) {
665       if ((ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) ||
666           (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED)) {
667         if (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) {
668           max_file_size = T4T_FC_TLV_OFFSET_IN_CC + T4T_FILE_CONTROL_TLV_SIZE;
669         } else {
670           max_file_size = ce_cb.mem.t4t.max_file_size;
671         }
672 
673         /*CLA+INS+Offset(P1P2)+Le = 5 bytes*/
674         if (p_c_apdu->len < T4T_CMD_MAX_HDR_SIZE) {
675           LOG(ERROR) << "Wrong length";
676           android_errorWriteLog(0x534e4554, "120845341");
677           GKI_freebuf(p_c_apdu);
678           ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
679           return;
680         }
681         BE_STREAM_TO_UINT16(offset, p_cmd); /* Offset */
682         BE_STREAM_TO_UINT8(length, p_cmd);  /* Le     */
683 
684         /* check if valid parameters */
685         if ((uint32_t)length <= CE_T4T_MAX_LE) {
686           /* CE allows to read more than current file size but not max file size
687            */
688           if (length + offset > max_file_size) {
689             if (offset < max_file_size) {
690               length = (uint8_t)(max_file_size - offset);
691 
692               DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
693                   "CET4T: length is reduced to %d by max_file_size (%d)",
694                   length, max_file_size);
695             } else {
696               LOG(ERROR) << StringPrintf(
697                   "CET4T: offset (%d) must be less than max_file_size (%d)",
698                   offset, max_file_size);
699               length = 0;
700             }
701           }
702         } else {
703           LOG(ERROR) << StringPrintf(
704               "CET4T: length (%d) must be less than MLe (%zu)", length,
705               CE_T4T_MAX_LE);
706           length = 0;
707         }
708 
709         if (length > 0)
710           ce_t4t_read_binary(offset, length);
711         else
712           ce_t4t_send_status(T4T_RSP_WRONG_PARAMS);
713       } else {
714         LOG(ERROR) << StringPrintf("CET4T: File has not been selected");
715         ce_t4t_send_status(T4T_RSP_CMD_NOT_ALLOWED);
716       }
717     } else if (instruct == T4T_CMD_INS_UPDATE_BINARY) {
718       if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY) {
719         LOG(ERROR) << StringPrintf("CET4T: No access right");
720         ce_t4t_send_status(T4T_RSP_CMD_NOT_ALLOWED);
721       } else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED) {
722         /*CLA+INS+Offset(P1P2)+Lc = 5 bytes*/
723         if (p_c_apdu->len < T4T_CMD_MAX_HDR_SIZE) {
724           LOG(ERROR) << "Wrong length";
725           android_errorWriteLog(0x534e4554, "120845341");
726           GKI_freebuf(p_c_apdu);
727           ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
728           return;
729         }
730         BE_STREAM_TO_UINT16(offset, p_cmd); /* Offset */
731         BE_STREAM_TO_UINT8(length, p_cmd);  /* Lc     */
732 
733         /* check if valid parameters */
734         if ((uint32_t)length <= CE_T4T_MAX_LC &&
735             /* check if data fits into the apdu */
736             (uint16_t)length <= p_c_apdu->len - T4T_CMD_MAX_HDR_SIZE) {
737           if (length + offset > ce_cb.mem.t4t.max_file_size) {
738             LOG(ERROR) << StringPrintf(
739                 "CET4T: length (%d) + offset (%d) must be less than "
740                 "max_file_size (%d)",
741                 length, offset, ce_cb.mem.t4t.max_file_size);
742             length = 0;
743           }
744         } else {
745           LOG(ERROR) << StringPrintf(
746               "CET4T: length (%d) must be less than MLc (%zu)", length,
747               CE_T4T_MAX_LC);
748           android_errorWriteLog(0x534e4554, "157649298");
749           length = 0;
750         }
751 
752         if (length > 0)
753           ce_t4t_update_binary(offset, length, p_cmd);
754         else
755           ce_t4t_send_status(T4T_RSP_WRONG_PARAMS);
756       } else {
757         LOG(ERROR) << StringPrintf("CET4T: NDEF File has not been selected");
758         ce_t4t_send_status(T4T_RSP_CMD_NOT_ALLOWED);
759       }
760     } else {
761       LOG(ERROR) << StringPrintf("CET4T: Unsupported Instruction byte (0x%02X)",
762                                  instruct);
763       ce_t4t_send_status(T4T_RSP_INSTR_NOT_SUPPORTED);
764     }
765   } else {
766     LOG(ERROR) << StringPrintf("CET4T: Application has not been selected");
767     ce_t4t_send_status(T4T_RSP_CMD_NOT_ALLOWED);
768   }
769 
770   if (p_c_apdu) GKI_freebuf(p_c_apdu);
771 }
772 
773 /*******************************************************************************
774 **
775 ** Function         ce_select_t4t
776 **
777 ** Description      Select Type 4 Tag
778 **
779 ** Returns          NFC_STATUS_OK if success
780 **
781 *******************************************************************************/
ce_select_t4t(void)782 tNFC_STATUS ce_select_t4t(void) {
783   tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
784 
785   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
786 
787   nfc_stop_quick_timer(&p_t4t->timer);
788 
789   /* clear other than read-only flag */
790   p_t4t->status &= CE_T4T_STATUS_NDEF_FILE_READ_ONLY;
791 
792   NFC_SetStaticRfCback(ce_t4t_data_cback);
793 
794   return NFC_STATUS_OK;
795 }
796 
797 /*******************************************************************************
798 **
799 ** Function         CE_T4tSetLocalNDEFMsg
800 **
801 ** Description      Initialise CE Type 4 Tag with mandatory NDEF message
802 **
803 **                  The following event may be returned
804 **                      CE_T4T_UPDATE_START_EVT for starting update
805 **                      CE_T4T_UPDATE_CPLT_EVT for complete update
806 **                      CE_T4T_UPDATE_ABORT_EVT for failure of update
807 **                      CE_T4T_RAW_FRAME_EVT for raw frame
808 **
809 **                  read_only:      TRUE if read only
810 **                  ndef_msg_max:   Max NDEF message size
811 **                  ndef_msg_len:   NDEF message size
812 **                  p_ndef_msg:     NDEF message (excluding NLEN)
813 **                  p_scratch_buf:  temp storage for update
814 **
815 ** Returns          NFC_STATUS_OK if success
816 **
817 *******************************************************************************/
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)818 tNFC_STATUS CE_T4tSetLocalNDEFMsg(bool read_only, uint16_t ndef_msg_max,
819                                   uint16_t ndef_msg_len, uint8_t* p_ndef_msg,
820                                   uint8_t* p_scratch_buf) {
821   tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
822   uint8_t* p;
823 
824   DLOG_IF(INFO, nfc_debug_enabled)
825       << StringPrintf("read_only=%d, ndef_msg_max=%d, ndef_msg_len=%d",
826                       read_only, ndef_msg_max, ndef_msg_len);
827 
828   if (!p_ndef_msg) {
829     p_t4t->p_ndef_msg = nullptr;
830 
831     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("T4T is disabled");
832     return NFC_STATUS_OK;
833   }
834 
835   if ((!read_only) && (!p_scratch_buf)) {
836     LOG(ERROR) << StringPrintf(
837         "p_scratch_buf cannot be NULL if not "
838         "read-only");
839     return NFC_STATUS_FAILED;
840   }
841 
842 #if (CE_TEST_INCLUDED == TRUE)
843   mapping_aid_test_enabled = false;
844 #endif
845 
846   /* Initialise CC file */
847   p = p_t4t->cc_file;
848 
849   UINT16_TO_BE_STREAM(p, T4T_CC_FILE_MIN_LEN);
850   UINT8_TO_BE_STREAM(p, T4T_MY_VERSION);
851   UINT16_TO_BE_STREAM(p, CE_T4T_MAX_LE);
852   UINT16_TO_BE_STREAM(p, CE_T4T_MAX_LC);
853 
854   /* Mandatory NDEF File Control TLV */
855   UINT8_TO_BE_STREAM(p, T4T_NDEF_FILE_CONTROL_TYPE);     /* type */
856   UINT8_TO_BE_STREAM(p, T4T_FILE_CONTROL_LENGTH);        /* length */
857   UINT16_TO_BE_STREAM(p, CE_T4T_MANDATORY_NDEF_FILE_ID); /* file ID */
858   UINT16_TO_BE_STREAM(
859       p, ndef_msg_max + T4T_FILE_LENGTH_SIZE); /* max NDEF file size */
860   UINT8_TO_BE_STREAM(p, T4T_FC_READ_ACCESS);   /* read access */
861 
862   if (read_only) {
863     UINT8_TO_BE_STREAM(p, T4T_FC_NO_WRITE_ACCESS); /* read only */
864     p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_READ_ONLY;
865   } else {
866     UINT8_TO_BE_STREAM(p, T4T_FC_WRITE_ACCESS); /* write access */
867     p_t4t->status &= ~(CE_T4T_STATUS_NDEF_FILE_READ_ONLY);
868   }
869 
870   /* set mandatory NDEF file */
871   p_t4t->p_ndef_msg = p_ndef_msg;
872   p_t4t->nlen = ndef_msg_len;
873   p_t4t->max_file_size = ndef_msg_max + T4T_FILE_LENGTH_SIZE;
874 
875   /* Initialize scratch buffer */
876   p_t4t->p_scratch_buf = p_scratch_buf;
877 
878   if (p_scratch_buf) {
879     memcpy(p_scratch_buf, p_ndef_msg, ndef_msg_len);
880   }
881 
882   return NFC_STATUS_OK;
883 }
884 
885 /*******************************************************************************
886 **
887 ** Function         CE_T4tRegisterAID
888 **
889 ** Description      Register AID in CE T4T
890 **
891 **                  aid_len: length of AID (up to NFC_MAX_AID_LEN)
892 **                  p_aid:   AID
893 **                  p_cback: Raw frame will be forwarded with CE_RAW_FRAME_EVT
894 **
895 ** Returns          tCE_T4T_AID_HANDLE if successful,
896 **                  CE_T4T_AID_HANDLE_INVALID otherwisse
897 **
898 *******************************************************************************/
CE_T4tRegisterAID(uint8_t aid_len,uint8_t * p_aid,tCE_CBACK * p_cback)899 tCE_T4T_AID_HANDLE CE_T4tRegisterAID(uint8_t aid_len, uint8_t* p_aid,
900                                      tCE_CBACK* p_cback) {
901   tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
902   uint8_t xx;
903 
904   /* Handle registering callback for wildcard AID (all AIDs) */
905   if (aid_len == 0) {
906     DLOG_IF(INFO, nfc_debug_enabled)
907         << StringPrintf("registering callback for wildcard AID ");
908 
909     /* Check if a wildcard callback is already registered (only one is allowed)
910      */
911     if (p_t4t->p_wildcard_aid_cback != nullptr) {
912       LOG(ERROR) << StringPrintf(
913           "only one wildcard AID can be registered at "
914           "time.");
915       return CE_T4T_AID_HANDLE_INVALID;
916     }
917 
918     DLOG_IF(INFO, nfc_debug_enabled)
919         << StringPrintf("handle 0x%02x registered (for wildcard AID)",
920                         CE_T4T_WILDCARD_AID_HANDLE);
921     p_t4t->p_wildcard_aid_cback = p_cback;
922     return CE_T4T_WILDCARD_AID_HANDLE;
923   }
924 
925   DLOG_IF(INFO, nfc_debug_enabled)
926       << StringPrintf("AID [%02X%02X%02X%02X...], %d bytes", *p_aid,
927                       *(p_aid + 1), *(p_aid + 2), *(p_aid + 3), aid_len);
928 
929   if (aid_len > NFC_MAX_AID_LEN) {
930     LOG(ERROR) << StringPrintf("AID is up to %d bytes", NFC_MAX_AID_LEN);
931     return CE_T4T_AID_HANDLE_INVALID;
932   }
933 
934   if (p_cback == nullptr) {
935     LOG(ERROR) << StringPrintf("callback must be provided");
936     return CE_T4T_AID_HANDLE_INVALID;
937   }
938 
939   for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) {
940     if ((p_t4t->reg_aid[xx].aid_len == aid_len) &&
941         (!(memcmp(p_t4t->reg_aid[xx].aid, p_aid, aid_len)))) {
942       LOG(ERROR) << StringPrintf("already registered");
943       return CE_T4T_AID_HANDLE_INVALID;
944     }
945   }
946 
947   for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) {
948     if (p_t4t->reg_aid[xx].aid_len == 0) {
949       p_t4t->reg_aid[xx].aid_len = aid_len;
950       p_t4t->reg_aid[xx].p_cback = p_cback;
951       memcpy(p_t4t->reg_aid[xx].aid, p_aid, aid_len);
952       break;
953     }
954   }
955 
956   if (xx >= CE_T4T_MAX_REG_AID) {
957     LOG(ERROR) << StringPrintf("No resource");
958     return CE_T4T_AID_HANDLE_INVALID;
959   } else {
960     DLOG_IF(INFO, nfc_debug_enabled)
961         << StringPrintf("handle 0x%02x registered", xx);
962   }
963 
964   return (xx);
965 }
966 
967 /*******************************************************************************
968 **
969 ** Function         CE_T4tDeregisterAID
970 **
971 ** Description      Deregister AID in CE T4T
972 **
973 ** Returns          NFC_STATUS_OK if success
974 **
975 *******************************************************************************/
CE_T4tDeregisterAID(tCE_T4T_AID_HANDLE aid_handle)976 extern void CE_T4tDeregisterAID(tCE_T4T_AID_HANDLE aid_handle) {
977   tCE_T4T_MEM* p_t4t = &ce_cb.mem.t4t;
978 
979   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("handle 0x%02x", aid_handle);
980 
981   /* Check if deregistering wildcard AID */
982   if (aid_handle == CE_T4T_WILDCARD_AID_HANDLE) {
983     if (p_t4t->p_wildcard_aid_cback != nullptr) {
984       p_t4t->p_wildcard_aid_cback = nullptr;
985     } else {
986       LOG(ERROR) << StringPrintf("Invalid handle");
987     }
988     return;
989   }
990 
991   /* Deregister AID */
992   if ((aid_handle >= CE_T4T_MAX_REG_AID) ||
993       (p_t4t->reg_aid[aid_handle].aid_len == 0)) {
994     LOG(ERROR) << StringPrintf("Invalid handle");
995   } else {
996     p_t4t->reg_aid[aid_handle].aid_len = 0;
997     p_t4t->reg_aid[aid_handle].p_cback = nullptr;
998   }
999 }
1000