• 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 <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