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