Implement response decryption and decapsulation

git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@152 f711b948-2313-0410-aaa9-d29f33439f0b
This commit is contained in:
hploetz 2006-11-27 04:17:09 +00:00
parent 1cc1433cd0
commit b9fc4b4487
1 changed files with 113 additions and 3 deletions

View File

@ -107,21 +107,58 @@ class TCOS_Security_Environment(object):
tlv_c_data = TLV_utils.unpack(self.last_c_apdu.data)
must_authenticate = False
must_decrypt = False
for data in tlv_c_data:
if data[0] & ~0x01 == 0xBA:
for response_template in data[2]:
if response_template[0] == 0x8E:
must_authenticate = True
if response_template[0] & ~0x01 in (0x84, 0x86):
must_decrypt = True
if must_authenticate:
if must_authenticate or must_decrypt:
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)
if must_authenticate:
tlv_data = self.authenticate_response(tlv_data)
if must_decrypt:
tlv_data = self.decrypt_response(tlv_data)
#data = TLV_utils.pack(tlv_data, recalculate_length = True)
data = self.deformat_response(tlv_data)
new_apdu = R_APDU(rapdu, data = data)
result = new_apdu
return result
def deformat_response(self, tlv_data):
WHITELIST = (0x84, 0x86)
result = []
is_ok = True
for data in tlv_data:
t = data[0] & ~0x01
if t not in WHITELIST and t in range(0x80, 0xBF+1):
is_ok = False # Unrecognized SM field present
if is_ok:
for data in tlv_data:
t = data[0] & ~0x01
value = data[2]
if t in WHITELIST:
if t == 0x86:
result.append( value[1:] )
else:
result.append( value )
else:
result.append( TLV_utils.pack( (data,), recalculate_length = True) )
else:
result.append( TLV_utils.pack( tlv_data, recalculate_length = True) )
return "".join(result)
def encrypt_command(self, tlv_data):
config = self.get_config(SE_APDU, TEMPLATE_CT)
@ -170,6 +207,66 @@ class TCOS_Security_Environment(object):
return result
def decrypt_response(self, tlv_data):
config = self.get_config(SE_RAPDU, TEMPLATE_CT)
if config.algorithm is None: ## FIXME: Find out the correct way to determine this
return tlv_data
result = []
for data in tlv_data:
tag, length, value = data[:3]
marks = len(data) > 3 and data[3] or ()
t = tag & ~(0x01)
if t == 0x84:
print
print "| Tag 0x%02x, length 0x%02x, encrypted (with ISO padding): " % (tag, length)
print "|| " + "\n|| ".join( utils.hexdump( value ).splitlines() )
value_ = crypto_utils.cipher( False,
self.get_cipherspec(config),
self.get_key(config),
value,
self.get_iv(config) )
print "| Decrypted result of length 0x%02x:" % len(value_)
print "|| " + "\n|| ".join( utils.hexdump(value_).splitlines() )
value = self.unpad(value_)
if False:
print "| Depadded result of length 0x%02x:" % len(value)
print "|| " + "\n|| ".join( utils.hexdump(value).splitlines() )
marks = marks + (self.MARK_ENCRYPT,)
elif t == 0x86:
pi = value[0]
print
print "| Tag 0x%02x, length 0x%02x, decrypting (with padding type %x): " % (tag, length, ord(pi))
print "|| " + "\n|| ".join( utils.hexdump( value[1:] ).splitlines() )
value_ = crypto_utils.cipher( False,
self.get_cipherspec(config),
self.get_key(config),
value[1:],
self.get_iv(config) )
print "| Decrypted result of length 0x%02x:" % len(value_)
print "|| " + "\n|| ".join( utils.hexdump(value_).splitlines() )
value = self.unpad(value_, ord(pi))
if False:
print "| Depadded result of length 0x%02x:" % len(value)
print "|| " + "\n|| ".join( utils.hexdump(value).splitlines() )
value = pi + value
marks = marks + (self.MARK_ENCRYPT,)
result.append( (tag, length, value, marks) )
return result
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."""
@ -306,6 +403,19 @@ class TCOS_Security_Environment(object):
else:
raise ValueError, "Unknown padding indicator %s" % pi
def unpad(self, data, pi = 1):
if pi == 1:
pos = len(data)-1
while ord(data[pos]) != 0x80:
if ord(data[pos]) != 0x00:
raise ValueError, "Padding error"
pos = pos - 1
return data[:pos]
elif pi == 2:
return data
else:
raise ValueError, "Unknown padding indicator %s" % pi
def parse_mse(self, apdu):
assert apdu.p1 & 0x0f == 1
operation = apdu.p2