/* * Get a pointer to the next record in the provided TLV sequence. * | 0x03 | 0x02 | 0xbe | 0xef | 0x00 | 0x00 | 0xfe | * First call ---' | | * Second call -------------------------------' | * Third call --------------------------------------' * Fourth call NULL */ uint8_t * tlv_next (uint8_t *stream) { uint8_t *res = NULL; if (stream[0] != TLV_TERMINATOR) res = stream + tlv_record_length (stream, NULL, NULL); return res; }
/* * Full-length of all TLV fields. */ size_t tlv_sequence_length (uint8_t *stream) { size_t res = 0; do { res += tlv_record_length (stream, NULL, NULL); } while ((stream = tlv_next (stream))); return res; }
/* * Decode TLV from data stream. */ uint8_t * tlv_decode (const uint8_t *istream, uint8_t *type, uint16_t *size) { size_t fls = 0; size_t fvs = 0; uint8_t *res = NULL; if (type) *type = istream[0]; tlv_record_length (istream, &fls, &fvs); if (size) { *size = fvs; } if ((res = malloc (fvs))) { memcpy (res, istream + 1 + fls, fvs); } return res; }
int mifare_classic_read_ndef(MifareTag tag, char * buffer, char *max_size) { int error = EXIT_SUCCESS; Mad mad; // NFCForum card has a MAD, load it. if (0 == mifare_classic_connect (tag)) { } else { return -2; } if ((mad = mad_read (tag))) { // Dump the NFCForum application using MAD information ssize_t len; if ((len = mifare_application_read (tag, mad, mad_nfcforum_aid, buffer, max_size, mifare_classic_nfcforum_public_key_a, MFC_KEY_A)) != -1) { uint8_t tlv_type; uint16_t tlv_data_len; uint8_t * tlv_data; uint8_t * pbuffer = buffer; uint8_t found = false; while (!found) { tlv_data = tlv_decode (pbuffer, &tlv_type, &tlv_data_len); switch (tlv_type) { case 0x00: printf ("NFC Forum application contains a \"NULL TLV\", Skipping...\n"); // According to [ANNFC1K4K], we skip this Tag to read further TLV blocks. pbuffer += tlv_record_length(pbuffer, NULL, NULL); if (pbuffer >= buffer + sizeof(buffer)) { error= -3; found = true; } break; case 0x03: printf ("NFC Forum application contains a \"NDEF Message TLV\".\n"); found = true; error = tlv_data_len; memcpy(buffer,tlv_data,tlv_data_len); break; case 0xFD: printf ("NFC Forum application contains a \"Proprietary TLV\", Skipping...\n"); // According to [ANNFC1K4K], we can skip this TLV to read further TLV blocks. pbuffer += tlv_record_length(pbuffer, NULL, NULL); if (pbuffer >= buffer + sizeof(buffer)) { error= -4; found = true; } break; case 0xFE: printf ("NFC Forum application contains a \"Terminator TLV\", no available data.\n"); error= -5; found = true; break; default: printf ("NFC Forum application contains an invalid TLV.\n"); error= -6; found = true; } } } else { printf ("No NFC Forum application.\n"); error= -7; } } else { printf ("No MAD detected.\n"); } vPortFree (mad); return error; }