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