iso7816: dissect ATR (answer to reset)

svn path=/trunk/; revision=42814
This commit is contained in:
Pascal Quantin 2012-05-23 20:51:38 +00:00
parent 84bfae28e0
commit 25e70c04d7
1 changed files with 172 additions and 9 deletions

View File

@ -36,12 +36,27 @@
#include <glib.h>
#include <epan/packet.h>
#include <epan/expert.h>
static int proto_iso7816 = -1;
static int ett_iso7816 = -1;
static int ett_iso7816_atr_td = -1;
static int hf_iso7816_atr = -1;
static int hf_iso7816_atr_init_char = -1;
static int hf_iso7816_atr_t0 = -1;
static int hf_iso7816_atr_ta = -1;
static int hf_iso7816_atr_tb = -1;
static int hf_iso7816_atr_tc = -1;
static int hf_iso7816_atr_td = -1;
static int hf_iso7816_atr_next_ta_present = -1;
static int hf_iso7816_atr_next_tb_present = -1;
static int hf_iso7816_atr_next_tc_present = -1;
static int hf_iso7816_atr_next_td_present = -1;
static int hf_iso7816_atr_k = -1;
static int hf_iso7816_atr_t = -1;
static int hf_iso7816_atr_hist_bytes = -1;
static int hf_iso7816_atr_tck = -1;
static int hf_iso7816_cla = -1;
static int hf_iso7816_ins = -1;
static int hf_iso7816_p1 = -1;
@ -55,6 +70,12 @@ static int hf_iso7816_sw2 = -1;
#define ADDR_INTF "Interface"
#define ADDR_CARD "Card"
static const value_string iso7816_atr_init_char[] = {
{ 0x3B, "Direct convention (A==0, Z==1, MSB==m9)" },
{ 0x3F, "Inverse convention (A==1, Z==0, MSB==m2)" },
{ 0, NULL }
};
static const value_string iso7816_ins[] = {
{ 0x0E, "Erase binary" },
{ 0x20, "Verify" },
@ -69,13 +90,102 @@ static const value_string iso7816_ins[] = {
static int
dissect_iso7816_atr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
gint offset = 0;
gint offset=0;
guint i=0; /* loop index for TA(i)...TD(i) */
proto_item *td_it;
proto_tree *td_tree=NULL;
guint8 ta, tb, tc, td, k=0;
gint tck_len;
proto_item *err_it;
col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "ATR sequence");
proto_tree_add_item(tree, hf_iso7816_atr, tvb, offset,
tvb_reported_length_remaining(tvb, offset), ENC_NA);
offset += tvb_reported_length_remaining(tvb, offset);
/* ISO 7816-4, section 4 indicates that concatenations are big endian */
proto_tree_add_item(tree, hf_iso7816_atr_init_char,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset++;
do {
/* for i==0, this is the T0 byte, otherwise it's the TD(i) byte
in each loop, we dissect T0/TD(i) and TA(i+1), TB(i+1), TC(i+1) */
td = tvb_get_guint8(tvb, offset);
if (i==0) {
td_it = proto_tree_add_item(tree, hf_iso7816_atr_t0,
tvb, offset, 1, ENC_BIG_ENDIAN);
}
else {
td_it = proto_tree_add_uint_format(tree, hf_iso7816_atr_td,
tvb, offset, 1, td,
"Interface character TD(%d): 0x%02x", i, td);
}
td_tree = proto_item_add_subtree(td_it, ett_iso7816_atr_td);
proto_tree_add_boolean_format(td_tree, hf_iso7816_atr_next_ta_present,
tvb, offset, 1, td&0x10,
"TA(%d) present: %s", i+1, td&0x10 ? "True" : "False");
proto_tree_add_boolean_format(td_tree, hf_iso7816_atr_next_tb_present,
tvb, offset, 1, td&0x20,
"TB(%d) present: %s", i+1, td&0x20 ? "True" : "False");
proto_tree_add_boolean_format(td_tree, hf_iso7816_atr_next_tc_present,
tvb, offset, 1, td&0x40,
"TC(%d) present: %s", i+1, td&0x40 ? "True" : "False");
proto_tree_add_boolean_format(td_tree, hf_iso7816_atr_next_td_present,
tvb, offset, 1, td&0x80,
"TD(%d) present: %s", i+1, td&0x80 ? "True" : "False");
if (i==0) {
k = td&0x0F; /* number of historical bytes */
proto_tree_add_item(td_tree, hf_iso7816_atr_k,
tvb, offset, 1, ENC_BIG_ENDIAN);
}
else {
proto_tree_add_item(td_tree, hf_iso7816_atr_t,
tvb, offset, 1, ENC_BIG_ENDIAN);
}
offset++;
if (td&0x10) {
ta = tvb_get_guint8(tvb, offset);
/* we read TA(i+1), see comment above */
proto_tree_add_uint_format(tree, hf_iso7816_atr_ta, tvb, offset, 1,
ta, "Interface character TA(%d): 0x%02x", i+1, ta);
offset++;
}
if (td&0x20) {
tb = tvb_get_guint8(tvb, offset);
proto_tree_add_uint_format(tree, hf_iso7816_atr_tb, tvb, offset, 1,
tb, "Interface character TB(%d): 0x%02x", i+1, tb);
offset++;
}
if (td&0x40) {
tc = tvb_get_guint8(tvb, offset);
proto_tree_add_uint_format(tree, hf_iso7816_atr_tc, tvb, offset, 1,
tc, "Interface character TC(%d): 0x%02x", i+1, tc);
offset++;
}
i++;
} while (td&0x80);
if (k>0) {
proto_tree_add_item(tree, hf_iso7816_atr_hist_bytes,
tvb, offset, k, ENC_NA);
offset += k;
}
tck_len = tvb_reported_length_remaining(tvb, offset);
/* tck is either absent or exactly one byte */
if (tck_len==1) {
proto_tree_add_item(tree, hf_iso7816_atr_tck,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset++;
}
else if (tck_len>1) {
err_it = proto_tree_add_text(tree, tvb, offset, tck_len,
"Invalid TCK byte");
expert_add_info_format(pinfo, err_it, PI_PROTOCOL, PI_WARN,
"TCK byte must either be absent or exactly one byte");
}
return offset;
}
@ -212,9 +322,61 @@ void
proto_register_iso7816(void)
{
static hf_register_info hf[] = {
{ &hf_iso7816_atr,
{ "ATR", "iso7816.atr",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
{ &hf_iso7816_atr_init_char,
{ "Initial character", "iso7816.atr.init_char",
FT_UINT8, BASE_HEX, VALS(iso7816_atr_init_char), 0, NULL, HFILL }
},
{ &hf_iso7816_atr_t0,
{ "Format character T0", "iso7816.atr.t0",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_iso7816_atr_ta,
{ "Interface character TA(i)", "iso7816.atr.ta",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_iso7816_atr_tb,
{ "Interface character TB(i)", "iso7816.atr.tb",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_iso7816_atr_tc,
{ "Interface character TC(i)", "iso7816.atr.tc",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_iso7816_atr_td,
{ "Interface character TD(i)", "iso7816.atr.td",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_iso7816_atr_next_ta_present,
{ "TA(i+1) present", "iso7816.atr.next_ta_present",
FT_BOOLEAN, BASE_HEX, NULL, 0x10, NULL, HFILL }
},
{ &hf_iso7816_atr_next_tb_present,
{ "TB(i+1) present", "iso7816.atr.next_tb_present",
FT_BOOLEAN, BASE_HEX, NULL, 0x20, NULL, HFILL }
},
{ &hf_iso7816_atr_next_tc_present,
{ "TC(i+1) present", "iso7816.atr.next_tc_present",
FT_BOOLEAN, BASE_HEX, NULL, 0x40, NULL, HFILL }
},
{ &hf_iso7816_atr_next_td_present,
{ "TD(i+1) present", "iso7816.atr.next_td_present",
FT_BOOLEAN, BASE_HEX, NULL, 0x80, NULL, HFILL }
},
{ &hf_iso7816_atr_k,
{ "Number K of historical bytes", "iso7816.atr.k",
FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
},
{ &hf_iso7816_atr_t,
{ "Protocol reference T", "iso7816.atr.t",
FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }
},
{ &hf_iso7816_atr_hist_bytes,
{ "Historical bytes", "iso7816.atr.historical_bytes",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_iso7816_atr_tck,
{ "Check character TCK", "iso7816.atr.tck",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_iso7816_cla,
{ "Class", "iso7816.apdu.cla",
@ -254,7 +416,8 @@ proto_register_iso7816(void)
}
};
static gint *ett[] = {
&ett_iso7816
&ett_iso7816,
&ett_iso7816_atr_td
};
proto_iso7816 = proto_register_protocol(