nicer TLV parsing, (more ugly code)
git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@59 f711b948-2313-0410-aaa9-d29f33439f0b
This commit is contained in:
parent
80c19becfa
commit
60c80e35c7
76
TLV_utils.py
76
TLV_utils.py
|
@ -8,6 +8,77 @@ binary = object()
|
|||
number = object()
|
||||
ascii = object()
|
||||
|
||||
file_descriptor_byte_descriptions = [
|
||||
#byte mask no match match
|
||||
(0x80, 0x80, None, "RFU"),
|
||||
(0xC0, 0x40, "non shareable", "shareable"),
|
||||
|
||||
(0xB8, 0x00, None, "working EF"),
|
||||
(0xB8, 0x08, None, "internal EF"),
|
||||
(0xB8, 0x10, None, "Reserved for proprietary uses"),
|
||||
(0xB8, 0x18, None, "Reserved for proprietary uses"),
|
||||
(0xB8, 0x20, None, "Reserved for proprietary uses"),
|
||||
(0xB8, 0x28, None, "Reserved for proprietary uses"),
|
||||
(0xB8, 0x30, None, "Reserved for proprietary uses"),
|
||||
(0xB8, 0x38, None, "DF"),
|
||||
|
||||
##(0x87, 0x00, None, "No EF structure information given"),
|
||||
(0x87, 0x01, None, "Transparent"),
|
||||
(0x87, 0x02, None, "Linear fixed, no further info"),
|
||||
(0x87, 0x03, None, "Linear fixed, SIMPLE-TLV"),
|
||||
(0x87, 0x04, None, "Linear variable, no further info"),
|
||||
(0x87, 0x05, None, "Linear variable, SIMPLE-TLV"),
|
||||
(0x87, 0x06, None, "Cyclic, no further info"),
|
||||
(0x87, 0x07, None, "Cyclic, SIMPLE-TLV"),
|
||||
]
|
||||
|
||||
data_coding_byte_descriptions = [
|
||||
(0x60, 0x00, None, "one-time write"),
|
||||
(0x60, 0x20, None, "proprietary"),
|
||||
(0x60, 0x40, None, "write OR"),
|
||||
(0x60, 0x60, None, "write AND"),
|
||||
]
|
||||
|
||||
def decode_file_descriptor_byte(value, verbose = True):
|
||||
result = " %s" % utils.hexdump(value, short=True)
|
||||
|
||||
if not verbose:
|
||||
attributes = utils.parse_binary(ord(value[0]), file_descriptor_byte_descriptions, False)
|
||||
if len(value) > 1:
|
||||
attributes.append(
|
||||
"data coding byte, behavior of write functions: %s, data unit size in in nibbles: %i" % (
|
||||
"".join( utils.parse_binary(ord(value[1]), data_coding_byte_descriptions) ),
|
||||
2 ** (ord(value[1])&0x07)
|
||||
)
|
||||
)
|
||||
|
||||
if len(value) > 2:
|
||||
i = 0
|
||||
for j in value[2:]:
|
||||
i = i * 256 + ord(j)
|
||||
attributes.append(
|
||||
"maximum record length: %s" % i
|
||||
)
|
||||
|
||||
return result + " (%s)" % "; ".join(attributes)
|
||||
else:
|
||||
result = result + "\nFile descriptor byte:\n"
|
||||
result = result + "\t" + "\n\t".join(
|
||||
utils.parse_binary(ord(value[0]), file_descriptor_byte_descriptions, True)
|
||||
)
|
||||
if len(value) > 1:
|
||||
result = result + "\nData coding byte (0x%02X):\n" % ord(value[1])
|
||||
result = result + "\tBehavior of write functions: %s\n\tData unit size in in nibbles: %i" % (
|
||||
"".join( utils.parse_binary(ord(value[1]), data_coding_byte_descriptions) ),
|
||||
2 ** (ord(value[1])&0x07)
|
||||
)
|
||||
if len(value) > 2:
|
||||
i = 0
|
||||
for j in value[2:]:
|
||||
i = i * 256 + ord(j)
|
||||
result = result + "\nMaximum record length: %s" % i
|
||||
return result
|
||||
|
||||
tags = {
|
||||
None: {
|
||||
0x62: (recurse, "File Control Parameters", context_FCP),
|
||||
|
@ -15,7 +86,7 @@ tags = {
|
|||
0x6F: (recurse, "File Control Information", context_FCI),
|
||||
0x80: (number, "Number of data bytes in the file, excluding structural information"),
|
||||
0x81: (number, "Number of data bytes in the file, including structural information"),
|
||||
0x82: (binary, "File descriptor byte"),
|
||||
0x82: (decode_file_descriptor_byte, "File descriptor byte"),
|
||||
0x83: (binary, "File identifier"),
|
||||
0x84: (binary, "DF name"),
|
||||
0x85: (binary, "Proprietary information"),
|
||||
|
@ -54,6 +125,8 @@ def decode(data, context = None, level = 0):
|
|||
current.append( " %s" % value)
|
||||
elif interpretation[0] is binary:
|
||||
current.append( " %s" % utils.hexdump(value, short=True))
|
||||
elif callable(interpretation[0]):
|
||||
current.append( ("\n"+"\t"*(level+1)).join(interpretation[0](value).splitlines()) )
|
||||
|
||||
result.append( "".join(current) )
|
||||
|
||||
|
@ -66,3 +139,4 @@ if __name__ == "__main__":
|
|||
|
||||
decoded = decode(test)
|
||||
print decoded
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class ISO_7816_4_Card(Card):
|
|||
|
||||
def cmd_parsetlv(self):
|
||||
"Decode the TLV data in the last response"
|
||||
print TLV_utils.decode(self.last_result)
|
||||
print TLV_utils.decode(self.last_result.data)
|
||||
|
||||
ATRS = list(Card.ATRS)
|
||||
ATRS.extend( [
|
||||
|
|
36
utils.py
36
utils.py
|
@ -1,5 +1,41 @@
|
|||
import pycsc, string, binascii, sys
|
||||
|
||||
def represent_binary_fancy(len, value, mask = 0):
|
||||
result = []
|
||||
for i in range(len):
|
||||
if i%4 == 0:
|
||||
result.append( " " )
|
||||
if i%8 == 0:
|
||||
result.append( " " )
|
||||
if mask & 0x01:
|
||||
result.append( str(value & 0x01) )
|
||||
else:
|
||||
result.append( "." )
|
||||
mask = mask >> 1
|
||||
value = value >> 2
|
||||
result.reverse()
|
||||
|
||||
return "".join(result).strip()
|
||||
|
||||
def parse_binary(value, bytemasks, verbose = False, value_len = 8):
|
||||
## Parses a binary structure and gives information back
|
||||
## bytemasks is a sequence of (mask, value, string_if_no_match, string_if_match) tuples
|
||||
result = []
|
||||
for mask, byte, nonmatch, match in bytemasks:
|
||||
|
||||
if verbose:
|
||||
prefix = represent_binary_fancy(value_len, byte, mask) + ": "
|
||||
else:
|
||||
prefix = ""
|
||||
if (value & mask) == (byte & mask):
|
||||
if match is not None:
|
||||
result.append(prefix + match)
|
||||
else:
|
||||
if nonmatch is not None:
|
||||
result.append(prefix + nonmatch)
|
||||
|
||||
return result
|
||||
|
||||
_myprintable = " " + string.letters + string.digits + string.punctuation
|
||||
def hexdump(data, indent = 0, short = False):
|
||||
r"""Generates a nice hexdump of data and returns it. Consecutive lines will
|
||||
|
|
Loading…
Reference in New Issue