somewhat more elegant implementation, allows 00 or ff filler bytes to be present

git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@148 f711b948-2313-0410-aaa9-d29f33439f0b
This commit is contained in:
hploetz 2006-11-26 05:10:04 +00:00
parent 58505948ea
commit 98034cf1f7
1 changed files with 82 additions and 74 deletions

View File

@ -89,10 +89,10 @@ class TCOS_Security_Environment(object):
def process_apdu(self, apdu):
if apdu.cla & 0x0c in (0x0c, 0x08):
tlv_data = TLV_utils.unpack(apdu.data, with_marks = apdu.marks)
tlv_data = TLV_utils.unpack(apdu.data, with_marks = apdu.marks, include_filler=True)
tlv_data = self.encrypt_command(tlv_data)
tlv_data = self.authenticate_apdu(apdu, tlv_data)
tlv_data = self.authenticate_command(apdu, tlv_data)
data = TLV_utils.pack(tlv_data, recalculate_length = True)
new_apdu = C_APDU(apdu, data = data)
@ -103,7 +103,6 @@ class TCOS_Security_Environment(object):
def process_rapdu(self, rapdu):
if self.last_c_apdu.cla & 0x0c in (0x0c, 0x08):
tlv_data = TLV_utils.unpack(rapdu.data)
tlv_c_data = TLV_utils.unpack(self.last_c_apdu.data)
must_authenticate = False
@ -112,21 +111,16 @@ class TCOS_Security_Environment(object):
for response_template in data[2]:
if response_template[0] == 0x8E:
must_authenticate = True
if must_authenticate:
for data in tlv_data:
if data[0] == 0x8E:
must_authenticate = False
tlv_data = self.authenticate_apdu(rapdu, tlv_data)
if must_authenticate:
print "| CRYPTOGRAPHIC CHECKSUM VERIFICATION ERROR"
print "| No cryptographic checksum was included in the response"
data = TLV_utils.pack(tlv_data, recalculate_length = True)
new_apdu = R_APDU(rapdu, data = data)
return new_apdu
tlv_data = TLV_utils.unpack(rapdu.data, include_filler=True)
tlv_data = self.authenticate_response(tlv_data)
data = TLV_utils.pack(tlv_data, recalculate_length = True)
new_apdu = R_APDU(rapdu, data = data)
return new_apdu
else:
return rapdu
else:
return rapdu
@ -139,7 +133,7 @@ class TCOS_Security_Environment(object):
result = []
for data in tlv_data:
tag, length, value, marks = data
if self.MARK_ENCRYPT in marks:
if self.MARK_ENCRYPT in marks and tag not in (0xff, 0x00):
t = tag & ~(0x01)
if t == 0x84:
value_ = self.pad(value)
@ -176,54 +170,40 @@ class TCOS_Security_Environment(object):
result.append(data[:3])
return result
def authenticate_apdu(self, apdu, tlv_data):
# FIXME: This method does not work correctly when there are 00 or ff fill bytes in the TLV stream
is_command = isinstance(apdu, C_APDU)
config = self.get_config(is_command and SE_APDU or SE_RAPDU, TEMPLATE_CCT)
if config.algorithm is None: ## FIXME: Find out the correct way to determine this
return tlv_data
print_buffer = False
for data in tlv_data:
if data[0] == 0x8E:
print_buffer = True
if not is_command: print
print "| Calculating cryptographic checksum:"
def calculate_cct(self, config, tlv_data, startblock = "", print_buffer=True):
"""Calculate the Cryptographic Checksum for some TLV data.
tlv_data MUST be of the format generated by the include_filler=True parameter to unpack."""
if print_buffer:
print "| Calculating cryptographic checksum:"
def do_block(buffer, block):
block = self.pad(block, pi = PI_ISO)
block_ = self.pad("".join(block), pi = PI_ISO)
offset = sum( [len(b) for b in buffer] )
buffer.append(block)
buffer.append(block_)
del block[:]
if print_buffer:
print "|| " + "\n|| ".join( utils.hexdump( block, offset = offset ).splitlines() )
print "|| " + "\n|| ".join( utils.hexdump( block_, offset = offset ).splitlines() )
buffer = []
if is_command and apdu.cla & 0x0c == 0x0c:
block = apdu.render()[:4]
do_block(buffer, block)
if startblock != "":
do_block(buffer, [startblock])
need_pad = False
block = ""
block = []
for data in tlv_data:
tag, length, value = data[:3]
if tag & 0x01 == 0x01 or tag not in range(0x80, 0xbf+1):
if (tag & 0x01 == 0x01 or tag not in range(0x80, 0xbf+1)) and tag not in (0xff, 0x00):
value_ = TLV_utils.pack( (data, ), recalculate_length=True )
block = block + value_
need_pad = True
block.append( value_ )
elif tag in (0xff, 0x00):
block.append( chr(tag) )
else:
if need_pad:
if len(block) > 0:
do_block(buffer, block)
block = ""
need_pad = False
if need_pad:
if len(block) > 0:
do_block(buffer, block)
block = ""
need_pad = False
cct = crypto_utils.cipher( True,
self.get_cipherspec(config),
@ -234,34 +214,62 @@ class TCOS_Security_Environment(object):
if print_buffer:
print "| Result (Tag 0x8e, length: 0x%02x):" % len(cct)
print "|| " + "\n|| ".join( utils.hexdump( cct ).splitlines() )
if is_command: print
return cct
def authenticate_command(self, apdu, tlv_data):
config = self.get_config(SE_APDU, TEMPLATE_CCT)
if config.algorithm is None: ## FIXME: Find out the correct way to determine this
return tlv_data
result = []
if is_command:
for data in tlv_data:
if data[0] == 0x8E:
data = list(data)
data[1] = len(cct)
data[2] = cct
data = tuple(data)
result.append( data )
else:
for data in tlv_data:
if data[0] == 0x8E:
value = data[2]
if len(value) >= 4 and cct.startswith(value):
print "| Cryptographic checksum verifies OK"
else:
print "| CRYPTOGRAPHIC CHECKSUM VERIFICATION ERROR"
print "| Is:"
print "|| " + "\n|| ".join( utils.hexdump( value ).splitlines() )
print "| Should be:"
print "|| " + "\n|| ".join( utils.hexdump( cct ).splitlines() )
else:
result.append( data )
for data in tlv_data:
if data[0] == 0x8e and data[1] == 0:
startblock = ""
if apdu.cla & 0x0c == 0x0c:
startblock = apdu.render()[:4]
cct = self.calculate_cct(config, tlv_data, startblock)
print
data = tuple( (0x8e, len(cct), cct) + data[3:] )
result.append(data)
return result
def authenticate_response(self, tlv_data):
config = self.get_config(SE_RAPDU, TEMPLATE_CCT)
if config.algorithm is None: ## FIXME: Find out the correct way to determine this
return tlv_data
print
cct_claimed = None
result = []
for data in tlv_data:
if data[0] == 0x8E:
cct_claimed = data[2]
else:
result.append( data )
if cct_claimed is None:
print "| CRYPTOGRAPHIC CHECKSUM VERIFICATION ERROR"
print "| No cryptographic checksum was included in the response"
return tlv_data
else:
cct = self.calculate_cct(config, tlv_data)
if len(cct_claimed) >= 4 and cct.startswith(cct_claimed):
print "| Cryptographic checksum verifies OK"
return result
else:
print "| CRYPTOGRAPHIC CHECKSUM VERIFICATION ERROR"
print "| Is:"
print "|| " + "\n|| ".join( utils.hexdump( cct_claimed ).splitlines() )
print "| Should be:"
print "|| " + "\n|| ".join( utils.hexdump( cct ).splitlines() )
return tlv_data
def get_cipherspec(self, config):
g = globals()