• 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 3 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_target.h"
34 
35 using android::base::StringPrintf;
36 
37 extern bool nfc_debug_enabled;
38 
39 enum {
40   CE_T3T_COMMAND_INVALID,
41   CE_T3T_COMMAND_NFC_FORUM,
42   CE_T3T_COMMAND_FELICA
43 };
44 
45 /* T3T CE states */
46 enum { CE_T3T_STATE_NOT_ACTIVATED, CE_T3T_STATE_IDLE, CE_T3T_STATE_UPDATING };
47 
48 /* Bitmasks to indicate type of UPDATE */
49 #define CE_T3T_UPDATE_FL_NDEF_UPDATE_START 0x01
50 #define CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT 0x02
51 #define CE_T3T_UPDATE_FL_UPDATE 0x04
52 
53 /*******************************************************************************
54  * Static constant definitions
55  *******************************************************************************/
56 /* Default PMm param */
57 static const uint8_t CE_DEFAULT_LF_PMM[NCI_T3T_PMM_LEN] = {
58     0x01, /* This PAD0 is used to identify HCE-F on Android */
59     0xFE, /* This PAD0 is used to identify HCE-F on Android */
60     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
61 
62 /*******************************************************************************
63 **
64 ** Function         ce_t3t_init
65 **
66 ** Description      Initialize tag-specific fields of ce control block
67 **
68 ** Returns          none
69 **
70 *******************************************************************************/
ce_t3t_init(void)71 void ce_t3t_init(void) {
72   memcpy(ce_cb.mem.t3t.local_pmm, CE_DEFAULT_LF_PMM, NCI_T3T_PMM_LEN);
73   ce_cb.mem.t3t.ndef_info.nbr = CE_T3T_DEFAULT_CHECK_MAXBLOCKS;
74   ce_cb.mem.t3t.ndef_info.nbw = CE_T3T_DEFAULT_UPDATE_MAXBLOCKS;
75 }
76 
77 /*******************************************************************************
78 **
79 ** Function         ce_t3t_send_to_lower
80 **
81 ** Description      Send C-APDU to lower layer
82 **
83 ** Returns          none
84 **
85 *******************************************************************************/
ce_t3t_send_to_lower(NFC_HDR * p_msg)86 void ce_t3t_send_to_lower(NFC_HDR* p_msg) {
87   uint8_t* p;
88 
89   /* Set NFC-F SoD field (payload len + 1) */
90   p_msg->offset -= 1; /* Point to SoD field */
91   p = (uint8_t*)(p_msg + 1) + p_msg->offset;
92   UINT8_TO_STREAM(p, (p_msg->len + 1));
93   p_msg->len += 1; /* Increment len to include SoD */
94 
95   if (NFC_SendData(NFC_RF_CONN_ID, p_msg) != NFC_STATUS_OK) {
96     LOG(ERROR) << StringPrintf("failed");
97   }
98 }
99 
100 /*******************************************************************************
101 **
102 ** Function         ce_t3t_is_valid_opcode
103 **
104 ** Description      Valid opcode
105 **
106 ** Returns          Type of command
107 **
108 *******************************************************************************/
ce_t3t_is_valid_opcode(uint8_t cmd_id)109 uint8_t ce_t3t_is_valid_opcode(uint8_t cmd_id) {
110   uint8_t retval = CE_T3T_COMMAND_INVALID;
111 
112   if ((cmd_id == T3T_MSG_OPC_CHECK_CMD) || (cmd_id == T3T_MSG_OPC_UPDATE_CMD)) {
113     retval = CE_T3T_COMMAND_NFC_FORUM;
114   } else if ((cmd_id == T3T_MSG_OPC_POLL_CMD) ||
115              (cmd_id == T3T_MSG_OPC_REQ_SERVICE_CMD) ||
116              (cmd_id == T3T_MSG_OPC_REQ_RESPONSE_CMD) ||
117              (cmd_id == T3T_MSG_OPC_REQ_SYSTEMCODE_CMD)) {
118     retval = CE_T3T_COMMAND_FELICA;
119   }
120 
121   return (retval);
122 }
123 
124 /*****************************************************************************
125 **
126 ** Function         ce_t3t_get_rsp_buf
127 **
128 ** Description      Get a buffer for sending T3T messages
129 **
130 ** Returns          NFC_HDR *
131 **
132 *****************************************************************************/
ce_t3t_get_rsp_buf(void)133 NFC_HDR* ce_t3t_get_rsp_buf(void) {
134   NFC_HDR* p_cmd_buf;
135 
136   p_cmd_buf = (NFC_HDR*)GKI_getpoolbuf(NFC_CE_POOL_ID);
137   if (p_cmd_buf != nullptr) {
138     /* Reserve offset for NCI_DATA_HDR and NFC-F Sod (LEN) field */
139     p_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + 1;
140     p_cmd_buf->len = 0;
141   }
142 
143   return (p_cmd_buf);
144 }
145 
146 /*******************************************************************************
147 **
148 ** Function         ce_t3t_send_rsp
149 **
150 ** Description      Send response to reader/writer
151 **
152 ** Returns          none
153 **
154 *******************************************************************************/
ce_t3t_send_rsp(tCE_CB * p_ce_cb,uint8_t * p_nfcid2,uint8_t opcode,uint8_t status1,uint8_t status2)155 void ce_t3t_send_rsp(tCE_CB* p_ce_cb, uint8_t* p_nfcid2, uint8_t opcode,
156                      uint8_t status1, uint8_t status2) {
157   tCE_T3T_MEM* p_cb = &p_ce_cb->mem.t3t;
158   NFC_HDR* p_rsp_msg;
159   uint8_t *p_dst, *p_rsp_start;
160 
161   /* If p_nfcid2 is NULL, then used activated NFCID2 */
162   if (p_nfcid2 == nullptr) {
163     p_nfcid2 = p_cb->local_nfcid2;
164   }
165 
166   p_rsp_msg = ce_t3t_get_rsp_buf();
167   if (p_rsp_msg != nullptr) {
168     p_dst = p_rsp_start = (uint8_t*)(p_rsp_msg + 1) + p_rsp_msg->offset;
169 
170     /* Response Code */
171     UINT8_TO_STREAM(p_dst, opcode);
172 
173     /* Manufacturer ID */
174     ARRAY_TO_STREAM(p_dst, p_nfcid2, NCI_RF_F_UID_LEN);
175 
176     /* Status1 and Status2 */
177     UINT8_TO_STREAM(p_dst, status1);
178     UINT8_TO_STREAM(p_dst, status2);
179 
180     p_rsp_msg->len = (uint16_t)(p_dst - p_rsp_start);
181     ce_t3t_send_to_lower(p_rsp_msg);
182   } else {
183     LOG(ERROR) << StringPrintf(
184         "CE: Unable to allocat buffer for response message");
185   }
186 }
187 
188 /*******************************************************************************
189 **
190 ** Function         ce_t3t_handle_update_cmd
191 **
192 ** Description      Handle UPDATE command from reader/writer
193 **
194 ** Returns          none
195 **
196 *******************************************************************************/
ce_t3t_handle_update_cmd(tCE_CB * p_ce_cb,NFC_HDR * p_cmd_msg)197 void ce_t3t_handle_update_cmd(tCE_CB* p_ce_cb, NFC_HDR* p_cmd_msg) {
198   tCE_T3T_MEM* p_cb = &p_ce_cb->mem.t3t;
199   uint8_t* p_temp;
200   uint8_t* p_block_list = p_cb->cur_cmd.p_block_list_start;
201   uint8_t* p_block_data = p_cb->cur_cmd.p_block_data_start;
202   uint8_t i, j, bl0;
203   uint16_t block_number, service_code, checksum, checksum_rx;
204   uint32_t newlen_hiword;
205   tCE_T3T_NDEF_INFO ndef_info;
206   tNFC_STATUS nfc_status = NFC_STATUS_OK;
207   uint8_t update_flags = 0;
208 
209   /* If in idle state, notify app that update is starting */
210   if (p_cb->state == CE_T3T_STATE_IDLE) {
211     p_cb->state = CE_T3T_STATE_UPDATING;
212   }
213 
214   for (i = 0; i < p_cb->cur_cmd.num_blocks; i++) {
215     /* Read byte0 of block list */
216     STREAM_TO_UINT8(bl0, p_block_list);
217 
218     if (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) {
219       STREAM_TO_UINT8(block_number, p_block_list);
220     } else {
221       STREAM_TO_UINT16(block_number, p_block_list);
222     }
223 
224     /* Read the block from memory */
225     service_code =
226         p_cb->cur_cmd.service_code_list[bl0 & T3T_MSG_SERVICE_LIST_MASK];
227 
228     /* Reject UPDATE command if service code=T3T_MSG_NDEF_SC_RO */
229     if (service_code == T3T_MSG_NDEF_SC_RO) {
230       /* Error: invalid block number to update */
231       LOG(ERROR) << StringPrintf("CE: UPDATE request using read-only service");
232       nfc_status = NFC_STATUS_FAILED;
233       break;
234     }
235 
236     /* Check for NDEF */
237     if (service_code == T3T_MSG_NDEF_SC_RW) {
238       if (p_cb->cur_cmd.num_blocks > p_cb->ndef_info.nbw) {
239         LOG(ERROR) << StringPrintf(
240             "CE: Requested too many blocks to update (requested: %i, max: %i)",
241             p_cb->cur_cmd.num_blocks, p_cb->ndef_info.nbw);
242         nfc_status = NFC_STATUS_FAILED;
243         break;
244       } else if (p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RO) {
245         LOG(ERROR) << StringPrintf(
246             "CE: error: write-request to read-only NDEF message.");
247         nfc_status = NFC_STATUS_FAILED;
248         break;
249       } else if (block_number == 0) {
250         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
251             "CE: Update sc 0x%04x block %i.", service_code, block_number);
252 
253         /* Special caes: NDEF block0 is the ndef attribute block */
254         p_temp = p_block_data;
255         STREAM_TO_UINT8(ndef_info.version, p_block_data);
256         p_block_data += 8; /* Ignore nbr,nbw,maxb,and reserved (reader/writer
257                               not allowed to update this) */
258         STREAM_TO_UINT8(ndef_info.writef, p_block_data);
259         p_block_data++; /* Ignore rwflag (reader/writer not allowed to update
260                            this) */
261         STREAM_TO_UINT8(newlen_hiword, p_block_data);
262         BE_STREAM_TO_UINT16(ndef_info.ln, p_block_data);
263         ndef_info.ln += (newlen_hiword << 16);
264         BE_STREAM_TO_UINT16(checksum_rx, p_block_data);
265 
266         checksum = 0;
267         for (j = 0; j < T3T_MSG_NDEF_ATTR_INFO_SIZE; j++) {
268           checksum += p_temp[j];
269         }
270 
271         /* Compare calcuated checksum with received checksum */
272         if (checksum != checksum_rx) {
273           LOG(ERROR) << StringPrintf(
274               "CE: Checksum failed for NDEF attribute block.");
275           nfc_status = NFC_STATUS_FAILED;
276         } else {
277           /* Update NDEF attribute block (only allowed to update current length
278            * and writef fields) */
279           p_cb->ndef_info.scratch_ln = ndef_info.ln;
280           p_cb->ndef_info.scratch_writef = ndef_info.writef;
281 
282           /* If writef=0 indicates completion of NDEF update */
283           if (ndef_info.writef == 0) {
284             update_flags |= CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT;
285           }
286           /* writef=1 indicates start of NDEF update */
287           else {
288             update_flags |= CE_T3T_UPDATE_FL_NDEF_UPDATE_START;
289           }
290         }
291       } else {
292         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
293             "CE: Udpate sc 0x%04x block %i.", service_code, block_number);
294 
295         /* Verify that block_number is within NDEF memory */
296         if (block_number > p_cb->ndef_info.nmaxb) {
297           /* Error: invalid block number to update */
298           LOG(ERROR) << StringPrintf(
299               "CE: Requested invalid NDEF block number to update %i (max is "
300               "%i).",
301               block_number, p_cb->ndef_info.nmaxb);
302           nfc_status = NFC_STATUS_FAILED;
303           break;
304         } else {
305           /* Update NDEF memory block */
306           STREAM_TO_ARRAY(
307               (&p_cb->ndef_info
308                     .p_scratch_buf[(block_number - 1) * T3T_MSG_BLOCKSIZE]),
309               p_block_data, T3T_MSG_BLOCKSIZE);
310         }
311 
312         /* Set flag to indicate that this UPDATE contained at least one block */
313         update_flags |= CE_T3T_UPDATE_FL_UPDATE;
314       }
315     } else {
316       /* Error: invalid service code */
317       LOG(ERROR) << StringPrintf("CE: Requested invalid service code: 0x%04x.",
318                                  service_code);
319       nfc_status = NFC_STATUS_FAILED;
320       break;
321     }
322   }
323 
324   /* Send appropriate response to reader/writer */
325   if (nfc_status == NFC_STATUS_OK) {
326     ce_t3t_send_rsp(p_ce_cb, nullptr, T3T_MSG_OPC_UPDATE_RSP,
327                     T3T_MSG_RSP_STATUS_OK, T3T_MSG_RSP_STATUS_OK);
328   } else {
329     ce_t3t_send_rsp(p_ce_cb, nullptr, T3T_MSG_OPC_UPDATE_RSP,
330                     T3T_MSG_RSP_STATUS_ERROR, T3T_MSG_RSP_STATUS2_ERROR_MEMORY);
331     p_cb->state = CE_T3T_STATE_IDLE;
332   }
333 
334   /* Notify the app of what got updated */
335   if (update_flags & CE_T3T_UPDATE_FL_NDEF_UPDATE_START) {
336     /* NDEF attribute got updated with WriteF=TRUE */
337     p_ce_cb->p_cback(CE_T3T_NDEF_UPDATE_START_EVT, nullptr);
338   }
339 
340   if (update_flags & CE_T3T_UPDATE_FL_UPDATE) {
341     /* UPDATE message contained at least one non-NDEF block */
342     p_ce_cb->p_cback(CE_T3T_UPDATE_EVT, nullptr);
343   }
344 
345   if (update_flags & CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT) {
346     /* NDEF attribute got updated with WriteF=FALSE */
347     tCE_DATA ce_data;
348     ce_data.update_info.status = nfc_status;
349     ce_data.update_info.p_data = p_cb->ndef_info.p_scratch_buf;
350     ce_data.update_info.length = p_cb->ndef_info.scratch_ln;
351     p_cb->state = CE_T3T_STATE_IDLE;
352     p_ce_cb->p_cback(CE_T3T_NDEF_UPDATE_CPLT_EVT, &ce_data);
353   }
354 
355   GKI_freebuf(p_cmd_msg);
356 }
357 
358 /*******************************************************************************
359 **
360 ** Function         ce_t3t_handle_check_cmd
361 **
362 ** Description      Handle CHECK command from reader/writer
363 **
364 ** Returns          Nothing
365 **
366 *******************************************************************************/
ce_t3t_handle_check_cmd(tCE_CB * p_ce_cb,NFC_HDR * p_cmd_msg)367 void ce_t3t_handle_check_cmd(tCE_CB* p_ce_cb, NFC_HDR* p_cmd_msg) {
368   tCE_T3T_MEM* p_cb = &p_ce_cb->mem.t3t;
369   NFC_HDR* p_rsp_msg;
370   uint8_t* p_rsp_start;
371   uint8_t *p_dst, *p_temp, *p_status;
372   uint8_t* p_src = p_cb->cur_cmd.p_block_list_start;
373   uint8_t i, bl0;
374   uint8_t ndef_writef;
375   uint32_t ndef_len;
376   uint16_t block_number, service_code, checksum;
377 
378   p_rsp_msg = ce_t3t_get_rsp_buf();
379   if (p_rsp_msg != nullptr) {
380     p_dst = p_rsp_start = (uint8_t*)(p_rsp_msg + 1) + p_rsp_msg->offset;
381 
382     /* Response Code */
383     UINT8_TO_STREAM(p_dst, T3T_MSG_OPC_CHECK_RSP);
384 
385     /* Manufacturer ID */
386     ARRAY_TO_STREAM(p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
387 
388     /* Save pointer to start of status field */
389     p_status = p_dst;
390 
391     /* Status1 and Status2 (assume success initially */
392     UINT8_TO_STREAM(p_dst, T3T_MSG_RSP_STATUS_OK);
393     UINT8_TO_STREAM(p_dst, T3T_MSG_RSP_STATUS_OK);
394     UINT8_TO_STREAM(p_dst, p_cb->cur_cmd.num_blocks);
395 
396     for (i = 0; i < p_cb->cur_cmd.num_blocks; i++) {
397       /* Read byte0 of block list */
398       STREAM_TO_UINT8(bl0, p_src);
399 
400       if (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) {
401         STREAM_TO_UINT8(block_number, p_src);
402       } else {
403         STREAM_TO_UINT16(block_number, p_src);
404       }
405 
406       /* Read the block from memory */
407       service_code =
408           p_cb->cur_cmd.service_code_list[bl0 & T3T_MSG_SERVICE_LIST_MASK];
409 
410       /* Check for NDEF */
411       if ((service_code == T3T_MSG_NDEF_SC_RO) ||
412           (service_code == T3T_MSG_NDEF_SC_RW)) {
413         /* Verify Nbr (NDEF only) */
414         if (p_cb->cur_cmd.num_blocks > p_cb->ndef_info.nbr) {
415           /* Error: invalid number of blocks to check */
416           LOG(ERROR) << StringPrintf(
417               "CE: Requested too many blocks to check (requested: %i, max: %i)",
418               p_cb->cur_cmd.num_blocks, p_cb->ndef_info.nbr);
419 
420           p_dst = p_status;
421           UINT8_TO_STREAM(p_dst, T3T_MSG_RSP_STATUS_ERROR);
422           UINT8_TO_STREAM(p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY);
423           break;
424         } else if (block_number == 0) {
425           /* Special caes: NDEF block0 is the ndef attribute block */
426           p_temp = p_dst;
427 
428           /* For rw ndef, use scratch buffer's attributes (in case reader/writer
429            * had previously updated NDEF) */
430           if ((p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RW) &&
431               (p_cb->ndef_info.p_scratch_buf)) {
432             ndef_writef = p_cb->ndef_info.scratch_writef;
433             ndef_len = p_cb->ndef_info.scratch_ln;
434           } else {
435             ndef_writef = p_cb->ndef_info.writef;
436             ndef_len = p_cb->ndef_info.ln;
437           }
438 
439           UINT8_TO_STREAM(p_dst, p_cb->ndef_info.version);
440           UINT8_TO_STREAM(p_dst, p_cb->ndef_info.nbr);
441           UINT8_TO_STREAM(p_dst, p_cb->ndef_info.nbw);
442           UINT16_TO_BE_STREAM(p_dst, p_cb->ndef_info.nmaxb);
443           UINT32_TO_STREAM(p_dst, 0);
444           UINT8_TO_STREAM(p_dst, ndef_writef);
445           UINT8_TO_STREAM(p_dst, p_cb->ndef_info.rwflag);
446           UINT8_TO_STREAM(p_dst, (ndef_len >> 16 & 0xFF));
447           UINT16_TO_BE_STREAM(p_dst, (ndef_len & 0xFFFF));
448 
449           checksum = 0;
450           for (int j = 0; j < T3T_MSG_NDEF_ATTR_INFO_SIZE; j++) {
451             checksum += p_temp[j];
452           }
453           UINT16_TO_BE_STREAM(p_dst, checksum);
454         } else {
455           /* Verify that block_number is within NDEF memory */
456           if (block_number > p_cb->ndef_info.nmaxb) {
457             /* Invalid block number */
458             p_dst = p_status;
459 
460             LOG(ERROR) << StringPrintf(
461                 "CE: Requested block number to check %i.", block_number);
462 
463             /* Error: invalid number of blocks to check */
464             UINT8_TO_STREAM(p_dst, T3T_MSG_RSP_STATUS_ERROR);
465             UINT8_TO_STREAM(p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY);
466             break;
467           } else {
468             /* If card is RW, then read from the scratch buffer (so reader/write
469              * can read back what it had just written */
470             if ((p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RW) &&
471                 (p_cb->ndef_info.p_scratch_buf)) {
472               ARRAY_TO_STREAM(
473                   p_dst,
474                   (&p_cb->ndef_info
475                         .p_scratch_buf[(block_number - 1) * T3T_MSG_BLOCKSIZE]),
476                   T3T_MSG_BLOCKSIZE);
477             } else {
478               ARRAY_TO_STREAM(
479                   p_dst,
480                   (&p_cb->ndef_info
481                         .p_buf[(block_number - 1) * T3T_MSG_BLOCKSIZE]),
482                   T3T_MSG_BLOCKSIZE);
483             }
484           }
485         }
486       } else {
487         /* Error: invalid service code */
488         LOG(ERROR) << StringPrintf(
489             "CE: Requested invalid service code: 0x%04x.", service_code);
490 
491         p_dst = p_status;
492         UINT8_TO_STREAM(p_dst, T3T_MSG_RSP_STATUS_ERROR);
493         UINT8_TO_STREAM(p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY);
494         break;
495       }
496     }
497 
498     p_rsp_msg->len = (uint16_t)(p_dst - p_rsp_start);
499     ce_t3t_send_to_lower(p_rsp_msg);
500   } else {
501     LOG(ERROR) << StringPrintf(
502         "CE: Unable to allocat buffer for response message");
503   }
504 
505   GKI_freebuf(p_cmd_msg);
506 }
507 
508 /*******************************************************************************
509 **
510 ** Function         ce_t3t_handle_non_nfc_forum_cmd
511 **
512 ** Description      Handle POLL command from reader/writer
513 **
514 ** Returns          Nothing
515 **
516 *******************************************************************************/
ce_t3t_handle_non_nfc_forum_cmd(tCE_CB * p_mem_cb,uint8_t cmd_id,NFC_HDR * p_cmd_msg)517 void ce_t3t_handle_non_nfc_forum_cmd(tCE_CB* p_mem_cb, uint8_t cmd_id,
518                                      NFC_HDR* p_cmd_msg) {
519   tCE_T3T_MEM* p_cb = &p_mem_cb->mem.t3t;
520   NFC_HDR* p_rsp_msg;
521   uint8_t* p_rsp_start;
522   uint8_t* p_dst;
523   uint8_t* p = (uint8_t*)(p_cmd_msg + 1) + p_cmd_msg->offset;
524   uint16_t sc;
525   uint8_t rc;
526   bool send_response = true;
527 
528   p_rsp_msg = ce_t3t_get_rsp_buf();
529   if (p_rsp_msg != nullptr) {
530     p_dst = p_rsp_start = (uint8_t*)(p_rsp_msg + 1) + p_rsp_msg->offset;
531 
532     switch (cmd_id) {
533       case T3T_MSG_OPC_POLL_CMD:
534         if (p_cmd_msg->len < 5) {
535           LOG(ERROR) << "Received invalid T3t message";
536           android_errorWriteLog(0x534e4554, "121150966");
537           send_response = false;
538           break;
539         }
540         /* Get system code and RC */
541         /* Skip over sod and cmd_id */
542         p += 2;
543         BE_STREAM_TO_UINT16(sc, p);
544         STREAM_TO_UINT8(rc, p);
545 
546         /* If requesting wildcard system code, or specifically our system code,
547          * then send POLL response */
548         if ((sc == 0xFFFF) || (sc == p_cb->system_code)) {
549           /* Response Code */
550           UINT8_TO_STREAM(p_dst, T3T_MSG_OPC_POLL_RSP);
551 
552           /* Manufacturer ID */
553           ARRAY_TO_STREAM(p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
554 
555           /* Manufacturer Parameter PMm */
556           ARRAY_TO_STREAM(p_dst, p_cb->local_pmm, NCI_T3T_PMM_LEN);
557 
558           /* If requesting system code */
559           if (rc == T3T_POLL_RC_SC) {
560             UINT16_TO_BE_STREAM(p_dst, p_cb->system_code);
561           }
562         } else {
563           send_response = false;
564         }
565         break;
566 
567       case T3T_MSG_OPC_REQ_RESPONSE_CMD:
568         /* Response Code */
569         UINT8_TO_STREAM(p_dst, T3T_MSG_OPC_REQ_RESPONSE_RSP);
570 
571         /* Manufacturer ID */
572         ARRAY_TO_STREAM(p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
573 
574         /* Mode */
575         UINT8_TO_STREAM(p_dst, 0);
576         break;
577 
578       case T3T_MSG_OPC_REQ_SYSTEMCODE_CMD:
579         /* Response Code */
580         UINT8_TO_STREAM(p_dst, T3T_MSG_OPC_REQ_SYSTEMCODE_RSP);
581 
582         /* Manufacturer ID */
583         ARRAY_TO_STREAM(p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
584 
585         /* Number of system codes */
586         UINT8_TO_STREAM(p_dst, 1);
587 
588         /* system codes */
589         UINT16_TO_BE_STREAM(p_dst, T3T_SYSTEM_CODE_NDEF);
590         break;
591 
592       case T3T_MSG_OPC_REQ_SERVICE_CMD:
593       default:
594         /* Unhandled command */
595         LOG(ERROR) << StringPrintf("Unhandled CE opcode: %02x", cmd_id);
596         send_response = false;
597         break;
598     }
599 
600     if (send_response) {
601       p_rsp_msg->len = (uint16_t)(p_dst - p_rsp_start);
602       ce_t3t_send_to_lower(p_rsp_msg);
603     } else {
604       GKI_freebuf(p_rsp_msg);
605     }
606   } else {
607     LOG(ERROR) << StringPrintf(
608         "CE: Unable to allocat buffer for response message");
609   }
610   GKI_freebuf(p_cmd_msg);
611 }
612 
613 /*******************************************************************************
614 **
615 ** Function         ce_t3t_data_cback
616 **
617 ** Description      This callback function receives the data from NFCC.
618 **
619 ** Returns          none
620 **
621 *******************************************************************************/
ce_t3t_data_cback(tNFC_DATA_CEVT * p_data)622 void ce_t3t_data_cback(tNFC_DATA_CEVT* p_data) {
623   tCE_CB* p_ce_cb = &ce_cb;
624   tCE_T3T_MEM* p_cb = &p_ce_cb->mem.t3t;
625   NFC_HDR* p_msg = p_data->p_data;
626   tCE_DATA ce_data;
627   uint8_t cmd_id, bl0, entry_len, i;
628   uint8_t* p_nfcid2 = nullptr;
629   uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
630   uint8_t cmd_nfcid2[NCI_RF_F_UID_LEN];
631   uint16_t block_list_start_offset, remaining;
632   bool msg_processed = false;
633   bool block_list_ok;
634   uint8_t sod;
635   uint8_t cmd_type;
636 
637   /* If activate system code is not NDEF, or if no local NDEF contents was set,
638    * then pass data up to the app */
639   if ((p_cb->system_code != T3T_SYSTEM_CODE_NDEF) ||
640       (!p_cb->ndef_info.initialized)) {
641     ce_data.raw_frame.status = p_data->status;
642     ce_data.raw_frame.p_data = p_msg;
643     p_ce_cb->p_cback(CE_T3T_RAW_FRAME_EVT, &ce_data);
644     return;
645   }
646 
647   /* Verify that message contains at least Sod and cmd_id */
648   if (p_msg->len < 2) {
649     LOG(ERROR) << StringPrintf(
650         "CE: received invalid T3t message (invalid length: %i)", p_msg->len);
651   } else {
652     /* Get and validate command opcode */
653     STREAM_TO_UINT8(sod, p);
654     STREAM_TO_UINT8(cmd_id, p);
655 
656     /* Valid command and message length */
657     cmd_type = ce_t3t_is_valid_opcode(cmd_id);
658     if (cmd_type == CE_T3T_COMMAND_INVALID) {
659       LOG(ERROR) << StringPrintf(
660           "CE: received invalid T3t message (invalid command: 0x%02X)", cmd_id);
661     } else if (cmd_type == CE_T3T_COMMAND_FELICA) {
662       ce_t3t_handle_non_nfc_forum_cmd(p_ce_cb, cmd_id, p_msg);
663       msg_processed = true;
664     } else {
665       /* Verify that message contains at least NFCID2 and NUM services */
666       if (p_msg->len < T3T_MSG_CMD_COMMON_HDR_LEN) {
667         LOG(ERROR) << StringPrintf(
668             "CE: received invalid T3t message (invalid length: %i)",
669             p_msg->len);
670       } else {
671         /* Handle NFC_FORUM command (UPDATE or CHECK) */
672         STREAM_TO_ARRAY(cmd_nfcid2, p, NCI_RF_F_UID_LEN);
673         STREAM_TO_UINT8(p_cb->cur_cmd.num_services, p);
674 
675         /* Validate num_services */
676         if (p_cb->cur_cmd.num_services > T3T_MSG_SERVICE_LIST_MAX) {
677           LOG(ERROR) << StringPrintf(
678               "CE: recieved num_services (%i) exceeds maximum (%i)",
679               p_cb->cur_cmd.num_services, T3T_MSG_SERVICE_LIST_MAX);
680         } else {
681           /* Calculate offset of block-list-start */
682           block_list_start_offset =
683               T3T_MSG_CMD_COMMON_HDR_LEN + 2 * p_cb->cur_cmd.num_services + 1;
684 
685           if (p_cb->state == CE_T3T_STATE_NOT_ACTIVATED) {
686             LOG(ERROR) << StringPrintf(
687                 "CE: received command 0x%02X while in bad state (%i))", cmd_id,
688                 p_cb->state);
689           } else if (memcmp(cmd_nfcid2, p_cb->local_nfcid2, NCI_RF_F_UID_LEN) !=
690                      0) {
691             LOG(ERROR) << StringPrintf(
692                 "CE: received invalid T3t message (invalid NFCID2)");
693             p_nfcid2 = cmd_nfcid2; /* respond with ERROR using the NFCID2 from
694                                       the command message */
695           } else if (p_msg->len < block_list_start_offset) {
696             /* Does not have minimum (including number_of_blocks field) */
697             LOG(ERROR) << StringPrintf("CE: incomplete message");
698           } else {
699             /* Parse service code list */
700             for (i = 0; i < p_cb->cur_cmd.num_services; i++) {
701               STREAM_TO_UINT16(p_cb->cur_cmd.service_code_list[i], p);
702             }
703 
704             /* Verify that block list */
705             block_list_ok = true;
706             STREAM_TO_UINT8(p_cb->cur_cmd.num_blocks, p);
707             remaining = p_msg->len - block_list_start_offset;
708             p_cb->cur_cmd.p_block_list_start = p;
709             for (i = 0; i < p_cb->cur_cmd.num_blocks; i++) {
710               /* Each entry is at lease 2 bytes long */
711               if (remaining < 2) {
712                 /* Unexpected end of message (while reading block-list) */
713                 LOG(ERROR) << StringPrintf(
714                     "CE: received invalid T3t message (unexpected end of "
715                     "block-list)");
716                 block_list_ok = false;
717                 break;
718               }
719 
720               /* Get byte0 of block-list entry */
721               bl0 = *p;
722 
723               /* Validate service code index and size of block-list */
724               if ((bl0 & T3T_MSG_SERVICE_LIST_MASK) >=
725                   p_cb->cur_cmd.num_services) {
726                 /* Invalid service code */
727                 LOG(ERROR) << StringPrintf(
728                     "CE: received invalid T3t message (invalid service index: "
729                     "%i)",
730                     (bl0 & T3T_MSG_SERVICE_LIST_MASK));
731                 block_list_ok = false;
732                 break;
733               } else if ((!(bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT)) &&
734                          (remaining < 3)) {
735                 /* Unexpected end of message (while reading 3-byte entry) */
736                 LOG(ERROR) << StringPrintf(
737                     "CE: received invalid T3t message (unexpected end of "
738                     "block-list)");
739                 block_list_ok = false;
740                 break;
741               }
742 
743               /* Advance pointers to next block-list entry */
744               entry_len =
745                   (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) ? 2 : 3;
746               p += entry_len;
747               remaining -= entry_len;
748             }
749 
750             /* Block list is verified. Call CHECK or UPDATE handler */
751             if (block_list_ok) {
752               p_cb->cur_cmd.p_block_data_start = p;
753               if (cmd_id == T3T_MSG_OPC_CHECK_CMD) {
754                 /* This is a CHECK command. Sanity check: there shouldn't be any
755                  * more data remaining after reading block list */
756                 if (remaining) {
757                   LOG(ERROR) << StringPrintf(
758                       "CE: unexpected data after after CHECK command (%u "
759                       "bytes)",
760                       (unsigned int)remaining);
761                 }
762                 ce_t3t_handle_check_cmd(p_ce_cb, p_msg);
763                 msg_processed = true;
764               } else {
765                 /* This is an UPDATE command. See if message contains all the
766                  * expected block data */
767                 if (remaining < p_cb->cur_cmd.num_blocks * T3T_MSG_BLOCKSIZE) {
768                   LOG(ERROR)
769                       << StringPrintf("CE: unexpected end of block-data");
770                 } else {
771                   ce_t3t_handle_update_cmd(p_ce_cb, p_msg);
772                   msg_processed = true;
773                 }
774               }
775             }
776           }
777         }
778       }
779     }
780   }
781 
782   if (!msg_processed) {
783     ce_t3t_send_rsp(p_ce_cb, p_nfcid2, T3T_MSG_OPC_CHECK_RSP,
784                     T3T_MSG_RSP_STATUS_ERROR,
785                     T3T_MSG_RSP_STATUS2_ERROR_PROCESSING);
786     GKI_freebuf(p_msg);
787   }
788 }
789 
790 /*******************************************************************************
791 **
792 ** Function         ce_t3t_conn_cback
793 **
794 ** Description      This callback function receives the events/data from NFCC.
795 **
796 ** Returns          none
797 **
798 *******************************************************************************/
ce_t3t_conn_cback(uint8_t conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)799 void ce_t3t_conn_cback(uint8_t conn_id, tNFC_CONN_EVT event,
800                        tNFC_CONN* p_data) {
801   tCE_T3T_MEM* p_cb = &ce_cb.mem.t3t;
802 
803   DLOG_IF(INFO, nfc_debug_enabled)
804       << StringPrintf("ce_t3t_conn_cback: conn_id=%i, evt=%i", conn_id, event);
805 
806   switch (event) {
807     case NFC_CONN_CREATE_CEVT:
808       break;
809 
810     case NFC_CONN_CLOSE_CEVT:
811       p_cb->state = CE_T3T_STATE_NOT_ACTIVATED;
812       break;
813 
814     case NFC_DATA_CEVT:
815       if (p_data->data.status == NFC_STATUS_OK) {
816         ce_t3t_data_cback(&p_data->data);
817       }
818       break;
819 
820     case NFC_DEACTIVATE_CEVT:
821       p_cb->state = CE_T3T_STATE_NOT_ACTIVATED;
822       NFC_SetStaticRfCback(nullptr);
823       break;
824 
825     default:
826       break;
827   }
828 }
829 
830 /*******************************************************************************
831 **
832 ** Function         ce_select_t3t
833 **
834 ** Description      Select Type 3 Tag
835 **
836 ** Returns          NFC_STATUS_OK if success
837 **
838 *******************************************************************************/
ce_select_t3t(uint16_t system_code,uint8_t nfcid2[NCI_RF_F_UID_LEN])839 tNFC_STATUS ce_select_t3t(uint16_t system_code,
840                           uint8_t nfcid2[NCI_RF_F_UID_LEN]) {
841   tCE_T3T_MEM* p_cb = &ce_cb.mem.t3t;
842 
843   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
844 
845   p_cb->state = CE_T3T_STATE_IDLE;
846   p_cb->system_code = system_code;
847   memcpy(p_cb->local_nfcid2, nfcid2, NCI_RF_F_UID_LEN);
848 
849   NFC_SetStaticRfCback(ce_t3t_conn_cback);
850   return NFC_STATUS_OK;
851 }
852 
853 /*******************************************************************************
854 **
855 ** Function         CE_T3tSetLocalNDEFMsg
856 **
857 ** Description      Initialise CE Type 3 Tag with mandatory NDEF message
858 **
859 ** Returns          NFC_STATUS_OK if success
860 **
861 *******************************************************************************/
CE_T3tSetLocalNDEFMsg(bool read_only,uint32_t size_max,uint32_t size_current,uint8_t * p_buf,uint8_t * p_scratch_buf)862 tNFC_STATUS CE_T3tSetLocalNDEFMsg(bool read_only, uint32_t size_max,
863                                   uint32_t size_current, uint8_t* p_buf,
864                                   uint8_t* p_scratch_buf) {
865   tCE_T3T_MEM* p_cb = &ce_cb.mem.t3t;
866 
867   DLOG_IF(INFO, nfc_debug_enabled)
868       << StringPrintf("CE_T3tSetContent: ro=%i, size_max=%i, size_current=%i",
869                       read_only, size_max, size_current);
870 
871   /* Verify scratch buffer was provided if NDEF message is read/write */
872   if ((!read_only) && (!p_scratch_buf)) {
873     LOG(ERROR) << StringPrintf(
874         "p_scratch_buf cannot be NULL if not "
875         "read-only");
876     return NFC_STATUS_FAILED;
877   }
878 
879   /* Check if disabling the local NDEF */
880   if (!p_buf) {
881     p_cb->ndef_info.initialized = false;
882   }
883   /* Save ndef attributes */
884   else {
885     p_cb->ndef_info.initialized = true;
886     /* Current length */
887     p_cb->ndef_info.ln = size_current;
888     /* Max length (in blocks) */
889     p_cb->ndef_info.nmaxb = (uint16_t)((size_max + 15) / T3T_MSG_BLOCKSIZE);
890     p_cb->ndef_info.rwflag =
891         (read_only) ? T3T_MSG_NDEF_RWFLAG_RO : T3T_MSG_NDEF_RWFLAG_RW;
892     p_cb->ndef_info.writef = T3T_MSG_NDEF_WRITEF_OFF;
893     p_cb->ndef_info.version = 0x10;
894     p_cb->ndef_info.p_buf = p_buf;
895     p_cb->ndef_info.p_scratch_buf = p_scratch_buf;
896 
897     /* Initiate scratch buffer with same contents as read-buffer */
898     if (p_scratch_buf) {
899       p_cb->ndef_info.scratch_ln = p_cb->ndef_info.ln;
900       p_cb->ndef_info.scratch_writef = T3T_MSG_NDEF_WRITEF_OFF;
901       memcpy(p_scratch_buf, p_buf, p_cb->ndef_info.ln);
902     }
903   }
904 
905   return (NFC_STATUS_OK);
906 }
907 
908 /*******************************************************************************
909 **
910 ** Function         CE_T3tSetLocalNDefParams
911 **
912 ** Description      Sets T3T-specific NDEF parameters. (Optional - if not
913 **                  called, then CE will use default parameters)
914 **
915 ** Returns          NFC_STATUS_OK if success
916 **
917 *******************************************************************************/
CE_T3tSetLocalNDefParams(uint8_t nbr,uint8_t nbw)918 tNFC_STATUS CE_T3tSetLocalNDefParams(uint8_t nbr, uint8_t nbw) {
919   tCE_T3T_MEM* p_cb = &ce_cb.mem.t3t;
920 
921   DLOG_IF(INFO, nfc_debug_enabled)
922       << StringPrintf("CE_T3tSetLocalNDefParams: nbr=%i, nbw=%i", nbr, nbw);
923 
924   /* Validate */
925   if ((nbr > T3T_MSG_NUM_BLOCKS_CHECK_MAX) ||
926       (nbw > T3T_MSG_NUM_BLOCKS_UPDATE_MAX) || (nbr < 1) || (nbw < 1)) {
927     LOG(ERROR) << StringPrintf("CE_T3tSetLocalNDefParams: invalid params");
928     return NFC_STATUS_FAILED;
929   }
930 
931   p_cb->ndef_info.nbr = nbr;
932   p_cb->ndef_info.nbw = nbw;
933 
934   return NFC_STATUS_OK;
935 }
936 
937 /*******************************************************************************
938 **
939 ** Function         CE_T3tSendCheckRsp
940 **
941 ** Description      Send CHECK response message
942 **
943 ** Returns          NFC_STATUS_OK if success
944 **
945 *******************************************************************************/
CE_T3tSendCheckRsp(uint8_t status1,uint8_t status2,uint8_t num_blocks,uint8_t * p_block_data)946 tNFC_STATUS CE_T3tSendCheckRsp(uint8_t status1, uint8_t status2,
947                                uint8_t num_blocks, uint8_t* p_block_data) {
948   tCE_T3T_MEM* p_cb = &ce_cb.mem.t3t;
949   tNFC_STATUS retval = NFC_STATUS_OK;
950   NFC_HDR* p_rsp_msg;
951   uint8_t *p_dst, *p_rsp_start;
952 
953   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
954       "CE_T3tCheckRsp: status1=0x%02X, status2=0x%02X, num_blocks=%i", status1,
955       status2, num_blocks);
956 
957   /* Validate num_blocks */
958   if (num_blocks > T3T_MSG_NUM_BLOCKS_CHECK_MAX) {
959     LOG(ERROR) << StringPrintf(
960         "CE_T3tCheckRsp num_blocks (%i) exceeds maximum (%i)", num_blocks,
961         T3T_MSG_NUM_BLOCKS_CHECK_MAX);
962     return (NFC_STATUS_FAILED);
963   }
964 
965   p_rsp_msg = ce_t3t_get_rsp_buf();
966   if (p_rsp_msg != nullptr) {
967     p_dst = p_rsp_start = (uint8_t*)(p_rsp_msg + 1) + p_rsp_msg->offset;
968 
969     /* Response Code */
970     UINT8_TO_STREAM(p_dst, T3T_MSG_OPC_CHECK_RSP);
971 
972     /* Manufacturer ID */
973     ARRAY_TO_STREAM(p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN);
974 
975     /* Status1 and Status2 */
976     UINT8_TO_STREAM(p_dst, status1);
977     UINT8_TO_STREAM(p_dst, status2);
978 
979     if (status1 == T3T_MSG_RSP_STATUS_OK) {
980       UINT8_TO_STREAM(p_dst, num_blocks);
981       ARRAY_TO_STREAM(p_dst, p_block_data, (num_blocks * T3T_MSG_BLOCKSIZE));
982     }
983 
984     p_rsp_msg->len = (uint16_t)(p_dst - p_rsp_start);
985     ce_t3t_send_to_lower(p_rsp_msg);
986   } else {
987     LOG(ERROR) << StringPrintf(
988         "CE: Unable to allocate buffer for response message");
989   }
990 
991   return (retval);
992 }
993 
994 /*******************************************************************************
995 **
996 ** Function         CE_T3tSendUpdateRsp
997 **
998 ** Description      Send UPDATE response message
999 **
1000 ** Returns          NFC_STATUS_OK if success
1001 **
1002 *******************************************************************************/
CE_T3tSendUpdateRsp(uint8_t status1,uint8_t status2)1003 tNFC_STATUS CE_T3tSendUpdateRsp(uint8_t status1, uint8_t status2) {
1004   tNFC_STATUS retval = NFC_STATUS_OK;
1005   tCE_CB* p_ce_cb = &ce_cb;
1006 
1007   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1008       "CE_T3tUpdateRsp: status1=0x%02X, status2=0x%02X", status1, status2);
1009   ce_t3t_send_rsp(p_ce_cb, nullptr, T3T_MSG_OPC_UPDATE_RSP, status1, status2);
1010 
1011   return (retval);
1012 }
1013