From a235dbd0a9d2ceb6bfaf0b7f4f0774c168ce334b Mon Sep 17 00:00:00 2001
From: Romain Tartiere <romain.tartiere@gmail.com>
Date: Wed, 23 Jun 2010 23:21:47 +0000
Subject: [PATCH] Fix TLV terminator.  0xFE is part of TLV, not NDEF.

---
 examples/mifare-classic-write-ndef.c | 11 ++++++++--
 libfreefare/tlv.c                    | 20 ++++++++++++++++--
 test/test_tlv.c                      | 31 ++++++++++++++--------------
 3 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/examples/mifare-classic-write-ndef.c b/examples/mifare-classic-write-ndef.c
index d568f2b..793845c 100644
--- a/examples/mifare-classic-write-ndef.c
+++ b/examples/mifare-classic-write-ndef.c
@@ -46,12 +46,12 @@ const MifareClassicKey default_keyb = {
     0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7
 };
 
-const uint8_t ndef_msg[34] = {
+const uint8_t ndef_msg[33] = {
     0xd1, 0x02, 0x1c, 0x53, 0x70, 0x91, 0x01, 0x09,
     0x54, 0x02, 0x65, 0x6e, 0x4c, 0x69, 0x62, 0x6e,
     0x66, 0x63, 0x51, 0x01, 0x0b, 0x55, 0x03, 0x6c,
     0x69, 0x62, 0x6e, 0x66, 0x63, 0x2e, 0x6f, 0x72,
-    0x67, 0xfe
+    0x67
 };
 
 int
@@ -239,6 +239,13 @@ main(int argc, char *argv[])
 		}
 	    }
 
+	    mifare_classic_trailer_block (&block, default_keyb, 0x0, 0x0, 0x0, 0x6, 0x40, default_keyb);
+	    if (mifare_classic_write (tags[i], 0x07, block) < 0) {
+		perror ("mifare_classic_write");
+		error = 1;
+		goto error;
+	    }
+
 	    free (tlv_data);
 
 	    free (mad);
diff --git a/libfreefare/tlv.c b/libfreefare/tlv.c
index e1162da..cdd0d55 100644
--- a/libfreefare/tlv.c
+++ b/libfreefare/tlv.c
@@ -17,6 +17,15 @@
  * $Id$
  */
 
+/*
+ * This implementation was written based on information provided by the
+ * following documents:
+ *
+ * NFC Forum - Type 1 Tag Operation Specification
+ *   NFCForum-TS-Type-1-Tag_1.0
+ *   2007-07-09
+ */
+
 #include "config.h"
 #include <stdlib.h>
 #include <string.h>
@@ -25,6 +34,8 @@
 
 #include <freefare.h>
 
+#define TLV_TERMINATOR 0xFE
+
 /*
  * TLV (Type Length Value) Manipulation Functions.
  */
@@ -44,7 +55,8 @@ tlv_encode (const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *
     if (isize == 0xffff) /* RFU */
 	return NULL;
 
-    if ((res = malloc (1 + ((isize > 254) ? 3 : 1) + isize))) {
+    if ((res = malloc (1 + ((isize > 254) ? 3 : 1) + isize + 1))) {
+	               /* type + size + payload + terminator */
 	res[n++] = type;
 
 	if (isize > 254) {
@@ -57,8 +69,12 @@ tlv_encode (const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *
 	}
 
 	memcpy (res + n, istream, isize);
+
+	n += isize;
+	res[n++] = TLV_TERMINATOR;
+
 	if (osize)
-	    *osize = isize + n;
+	    *osize = n;
     }
     return res;
 }
diff --git a/test/test_tlv.c b/test/test_tlv.c
index 6cdd0b1..060dc68 100644
--- a/test/test_tlv.c
+++ b/test/test_tlv.c
@@ -21,15 +21,15 @@
 
 #include <freefare.h>
 
-const uint8_t shortdata[]  = "elephant"; /* read: "elephant\0" = 9 bytes! */
-const uint8_t eshortdata[] = "\x03" "\x09" "elephant";
+const uint8_t shortdata[8]  = "elephant";
+const uint8_t eshortdata[11] = "\x03" "\x08" "elephant" "\xfe";
 
 			    /*
 			     * Many thanks to Charles Baudelaire for helping me
 			     * test things and helping you realize your f**king
 			     * OS / compiler does not support UTF-8 ;-)
 			     */
-const uint8_t longdata[] =  "Dans une terre grasse et pleine d'escargots\n"
+const uint8_t longdata[660] =  "Dans une terre grasse et pleine d'escargots\n"
                             "Je veux creuser moi-même une fosse profonde,\n"
 		            "Où je puisse à loisir étaler mes vieux os\n"
 		            "Et dormir dans l'oubli comme un requin dans l'onde.\n"
@@ -44,7 +44,7 @@ const uint8_t longdata[] =  "Dans une terre grasse et pleine d'escargots\n"
 		            "Et dites-moi s'il est encor quelque torture\n"
 		            "Pour ce vieux corps sans âme et mort parmi les morts!\n";
 
-const uint8_t elongdata[] = "\x07" "\xff\x02\x95"
+const uint8_t elongdata[665] = "\x07" "\xff\x02\x94"
                             "Dans une terre grasse et pleine d'escargots\n"
                             "Je veux creuser moi-même une fosse profonde,\n"
 		            "Où je puisse à loisir étaler mes vieux os\n"
@@ -58,7 +58,8 @@ const uint8_t elongdata[] = "\x07" "\xff\x02\x95"
 		            "Philosophes viveurs, fils de la pourriture,\n"
 		            "À travers ma ruine allez donc sans remords,\n"
 		            "Et dites-moi s'il est encor quelque torture\n"
-		            "Pour ce vieux corps sans âme et mort parmi les morts!\n";
+		            "Pour ce vieux corps sans âme et mort parmi les morts!\n"
+			    "\xfe";
 
 void
 test_tlv_encode_short (void)
@@ -67,10 +68,10 @@ test_tlv_encode_short (void)
     size_t osize;
 
     res = tlv_encode (3, shortdata, sizeof (shortdata), &osize);
-    cut_assert_equal_int (11, osize, cut_message ("Wrong encoded message length."));
+    cut_assert_equal_int (sizeof (eshortdata), osize, cut_message ("Wrong encoded message length."));
     cut_assert_equal_int (3, res[0], cut_message ("Wrong type"));
-    cut_assert_equal_int (9, res[1], cut_message ("Wrong value length"));
-    cut_assert_equal_memory (res, osize, eshortdata, sizeof (eshortdata), cut_message ("Wrong encoded value"));
+    cut_assert_equal_int (sizeof (shortdata), res[1], cut_message ("Wrong value length"));
+    cut_assert_equal_memory (eshortdata, sizeof (eshortdata), res, osize, cut_message ("Wrong encoded value"));
     free (res);
 }
 
@@ -81,12 +82,12 @@ test_tlv_encode_long (void)
     size_t osize;
 
     res = tlv_encode (7, longdata, sizeof (longdata), &osize);
-    cut_assert_equal_int (665, osize, cut_message ("Wrong encoded message length."));
+    cut_assert_equal_int (sizeof (elongdata), osize, cut_message ("Wrong encoded message length."));
     cut_assert_equal_int (7, res[0], cut_message ("Wrong type"));
     cut_assert_equal_int (0xff, res[1], cut_message ("Wrong value length"));
     cut_assert_equal_int (0x02, res[2], cut_message ("Wrong value length"));
-    cut_assert_equal_int (0x95, res[3], cut_message ("Wrong value length"));
-    cut_assert_equal_memory (res, osize, elongdata, sizeof (elongdata), cut_message ("Wrong encoded value"));
+    cut_assert_equal_int (0x94, res[3], cut_message ("Wrong value length"));
+    cut_assert_equal_memory (elongdata, sizeof (elongdata), res, osize, cut_message ("Wrong encoded value"));
     free (res);
 }
 
@@ -99,8 +100,8 @@ test_tlv_decode_short (void)
 
     res = tlv_decode (eshortdata, &type, &size);
     cut_assert_equal_int (3, type, cut_message ("Wrong type"));
-    cut_assert_equal_int (9, size, cut_message ("Wrong value length"));
-    cut_assert_equal_memory (res, size, shortdata, sizeof (shortdata), cut_message ("Wrong decoded value"));
+    cut_assert_equal_int (sizeof (shortdata), size, cut_message ("Wrong value length"));
+    cut_assert_equal_memory (shortdata, sizeof (shortdata), res, size, cut_message ("Wrong decoded value"));
     free (res);
 }
 
@@ -113,8 +114,8 @@ test_tlv_decode_long (void)
 
     res = tlv_decode (elongdata, &type, &size);
     cut_assert_equal_int (7, type, cut_message ("Wrong type"));
-    cut_assert_equal_int (0x295, size, cut_message ("Wrong value length"));
-    cut_assert_equal_memory (res, size, longdata, sizeof (longdata), cut_message ("Wrong decoded value"));
+    cut_assert_equal_int (sizeof (longdata), size, cut_message ("Wrong value length"));
+    cut_assert_equal_memory (longdata, sizeof (longdata), res, size, cut_message ("Wrong decoded value"));
     free (res);
 }