Even though there may be different Keys to protect CAPDUs and RAPDUs there is

only one Security Environment. Therefore, I merged the CAPDU_SE and RAPDU_SE
into current_SE. Works with the ePass Emulation, still need to test it with
the cryptoflex card.


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@446 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
oepen
2011-07-29 14:15:10 +00:00
parent 47461a40ca
commit d9f16f5a69

View File

@@ -427,10 +427,8 @@ class PassportSAM(SAM):
#SAM.__init__(self, path, key,None) #SAM.__init__(self, path, key,None)
SAM.__init__(self, None, None, mf) SAM.__init__(self, None, None, mf)
self.SM_handler = ePass_SM(mf, None, None, None) self.SM_handler = ePass_SM(mf, None, None, None)
self.SM_handler.CAPDU_SE.cct.algorithm = "CC" self.SM_handler.current_SE.cct.algorithm = "CC"
self.SM_handler.RAPDU_SE.cct.algorithm = "CC" self.SM_handler.current_SE.ct.algorithm = "DES3-CBC"
self.SM_handler.CAPDU_SE.ct.algorithm = "DES3-CBC"
self.SM_handler.RAPDU_SE.ct.algorithm = "DES3-CBC"
def __computeKeys(self): def __computeKeys(self):
"""Computes the keys depending on the machine readable """Computes the keys depending on the machine readable
@@ -487,15 +485,11 @@ class PassportSAM(SAM):
self.KSmac = self.derive_key(KSseed, 2) self.KSmac = self.derive_key(KSseed, 2)
#self.ssc = rnd_icc[-4:] + rnd_ifd[-4:] #self.ssc = rnd_icc[-4:] + rnd_ifd[-4:]
#Set the current SE #Set the current SE
self.SM_handler.CAPDU_SE.ct.key = self.KSenc self.SM_handler.current_SE.ct.key = self.KSenc
self.SM_handler.CAPDU_SE.cct.key = self.KSmac self.SM_handler.current_SE.cct.key = self.KSmac
self.SM_handler.RAPDU_SE.ct.key = self.KSenc
self.SM_handler.RAPDU_SE.cct.key = self.KSmac
self.SM_handler.ssc = stringtoint(rnd_icc[-4:] + rnd_ifd[-4:]) self.SM_handler.ssc = stringtoint(rnd_icc[-4:] + rnd_ifd[-4:])
self.SM_handler.CAPDU_SE.ct.algorithm = "DES3-CBC" self.SM_handler.current_SE.ct.algorithm = "DES3-CBC"
self.SM_handler.RAPDU_SE.ct.algorithm = "DES3-CBC" self.SM_handler.current_SE.cct.algorithm = "CC"
self.SM_handler.CAPDU_SE.cct.algorithm = "CC"
self.SM_handler.RAPDU_SE.cct.algorithm = "CC"
return SW["NORMAL"], Eicc + Micc return SW["NORMAL"], Eicc + Micc
def _mac(self, key, data, ssc = None, dopad=True): def _mac(self, key, data, ssc = None, dopad=True):
@@ -557,6 +551,10 @@ class Security_Environment(object):
self.dst = CRT(TEMPLATE_DST) self.dst = CRT(TEMPLATE_DST)
self.ct = CRT(TEMPLATE_CT) self.ct = CRT(TEMPLATE_CT)
self.capdu_sm = False
self.rapdu_sm = False
self.internal_auth = False
self.externel_auth = False
def mse(self,config): def mse(self,config):
structure = TLVutils.unpack(config) structure = TLVutils.unpack(config)
@@ -578,21 +576,15 @@ class Security_Environment(object):
class Secure_Messaging(object): class Secure_Messaging(object):
def __init__(self,MF,CAPDU_SE=None,RAPDU_SE=None): def __init__(self,MF,SE=None):
import virtualsmartcard.CryptoUtils import virtualsmartcard.CryptoUtils
self.mf = MF self.mf = MF
if not CAPDU_SE: if not SE:
self.CAPDU_SE = Security_Environment() self.current_SE = Security_Environment()
else: else:
self.CAPDU_SE = CAPDU_SE self.current_SE = SE
if not RAPDU_SE:
self.RAPDU_SE = Security_Environment()
else:
self.RAPDU_SE = RAPDU_SE
self.current_SE = Security_Environment()
def set_MF(self,mf): def set_MF(self,mf):
self.mf = mf self.mf = mf
@@ -620,13 +612,13 @@ class Secure_Messaging(object):
se = p1 >> 4 se = p1 >> 4
if(cmd == 0x01): if(cmd == 0x01):
if se & 0x01: #Secure messaging in command data field if se & 0x01: #Secure messaging in command data field
self.current_SE = self.CAPDU_SE self.current_SE.capdu_sm = True
if se & 0x02: #Secure messaging in response data field if se & 0x02: #Secure messaging in response data field
self.current_SE = self.RAPDU_SE self.current_SE.rapdu_sm = True
if se & 0x04: #Computation, decipherment, internal authentication and key agreement if se & 0x04: #Computation, decipherment, internal authentication and key agreement
pass self.current_SE.internal_auth = True
if se & 0x08: #Verification, encipherment, external authentication and key agreement if se & 0x08: #Verification, encipherment, external authentication and key agreement
pass self.current_SE.external_auth = True
self.__set_SE(p2,data) self.__set_SE(p2,data)
elif(cmd== 0x02): elif(cmd== 0x02):
self.__store_SE(p2) self.__store_SE(p2)
@@ -664,7 +656,7 @@ class Secure_Messaging(object):
Stores the current Security environment in the secure access module. The Stores the current Security environment in the secure access module. The
SEID is used as a reference to identify the SE. SEID is used as a reference to identify the SE.
""" """
SEstr = dumps(self.CAPDU_SE) SEstr = dumps(self.current_SE)
try: try:
self.SAM.addkey(SEID, SEstr) #TODO: Need SAM reference self.SAM.addkey(SEID, SEstr) #TODO: Need SAM reference
except ValueError: except ValueError:
@@ -679,9 +671,9 @@ class Secure_Messaging(object):
SEstr = self.SAM.get_key(SEID) SEstr = self.SAM.get_key(SEID)
SE = loads(SEstr) SE = loads(SEstr)
if isinstance(SE, SecurityEnvironment): if isinstance(SE, SecurityEnvironment):
self.CAPDU_SE = SE self.current_SE = SE
else: else:
raise ValueError raise SwError(SW["ERR_REFNOTUSABLE"])
def __erase_SE(self,SEID): def __erase_SE(self,SEID):
""" """
@@ -690,23 +682,6 @@ class Secure_Messaging(object):
self.SAM.removeKey(SEID) self.SAM.removeKey(SEID)
def parse_SM_CAPDU(self,CAPDU,header_authentication): def parse_SM_CAPDU(self,CAPDU,header_authentication):
"""
Frontend for the __parse_SM command. We set the right Security Environment and restore the
old one, when the command is finished
"""
current_SE = self.current_SE
self.current_SE = self.CAPDU_SE
try:
capdu = self.__parse_SM(CAPDU,header_authentication)
except SwError, e: #Restore Security Environment
self.current_SE = current_SE
raise e
self.current_SE = current_SE
return capdu
def __parse_SM(self,CAPDU,header_authentication):
""" """
This methods parses a data field including Secure Messaging objects. This methods parses a data field including Secure Messaging objects.
SM_header indicates wether or not the header of the message shall be authenticated SM_header indicates wether or not the header of the message shall be authenticated
@@ -790,7 +765,7 @@ class Secure_Messaging(object):
sw, plain = self.decipher(tag,0x80,value[1:]) sw, plain = self.decipher(tag,0x80,value[1:])
if sw != 0x9000: if sw != 0x9000:
raise ValueError raise ValueError
plain = virtualsmartcard.CryptoUtils.strip_padding(self.CAPDU_SE.ct.algorithm,plain,padding_indicator) plain = virtualsmartcard.CryptoUtils.strip_padding(self.current_SE.ct.algorithm,plain,padding_indicator)
return_data.append(plain) return_data.append(plain)
#SM data objects for authentication #SM data objects for authentication
@@ -838,23 +813,6 @@ class Secure_Messaging(object):
return c return c
def protect_response(self,sw,result): def protect_response(self,sw,result):
"""
Frontend for the __protect command. We set the right Security Environment and restore the
old one, when the command is finished
"""
current_SE = self.current_SE
self.current_SE = self.RAPDU_SE
try:
sw, data = self.__protect(sw,result)
except SwError, e: #Restore Security Environment
self.current_SE = current_SE
raise e
self.current_SE = current_SE
return sw, data
def __protect(self,sw,result):
""" """
This method protects a response APDU using secure messanging mechanisms This method protects a response APDU using secure messanging mechanisms
It returns the protected data and the SW bytes It returns the protected data and the SW bytes
@@ -878,15 +836,15 @@ class Secure_Messaging(object):
return_data += encrypted_tlv return_data += encrypted_tlv
if sw == SW["NORMAL"]: if sw == SW["NORMAL"]:
if self.CAPDU_SE.cct.algorithm == None: if self.current_SE.cct.algorithm == None:
raise SwError(SW["CONDITIONSNOTSATISFIED"]) raise SwError(SW["CONDITIONSNOTSATISFIED"])
elif self.CAPDU_SE.cct.algorithm == "CCT": elif self.current_SE.cct.algorithm == "CCT":
tag = SM_Class["CHECKSUM"] tag = SM_Class["CHECKSUM"]
to_auth = virtualsmartcard.CryptoUtils.append_padding("DES-ECB", return_data) to_auth = virtualsmartcard.CryptoUtils.append_padding("DES-ECB", return_data)
sw, auth = self.compute_cryptographic_checksum(0x8E, 0x80, to_auth) sw, auth = self.compute_cryptographic_checksum(0x8E, 0x80, to_auth)
length = len(auth) length = len(auth)
return_data += TLVutils.pack([(tag,length,auth)]) return_data += TLVutils.pack([(tag,length,auth)])
elif self.CAPDU_SE.cct.algorithm == "SIGNATURE": elif self.current_SE.cct.algorithm == "SIGNATURE":
tag = SM_Class["DIGITAL_SIGNATURE"] tag = SM_Class["DIGITAL_SIGNATURE"]
hash = self.hash(0x90, 0x80, return_data) hash = self.hash(0x90, 0x80, return_data)
sw, auth = self.compute_digital_signature(0x9E, 0x9A, hash) sw, auth = self.compute_digital_signature(0x9E, 0x9A, hash)
@@ -938,7 +896,7 @@ class Secure_Messaging(object):
""" """
if p1 != 0x8E or p2 != 0x80: if p1 != 0x8E or p2 != 0x80:
raise SwError(SW["ERR_INCORRECTP1P2"]) raise SwError(SW["ERR_INCORRECTP1P2"])
if self.CAPDU_SE.cct.algorithm == None or self.current_SE.cct.key == None: if self.current_SE.cct.key == None:
raise SwError(SE["ERR_CONDITIONNOTSATISFIED"]) raise SwError(SE["ERR_CONDITIONNOTSATISFIED"])
checksum = virtualsmartcard.CryptoUtils.crypto_checksum(self.current_SE.cct.algorithm, checksum = virtualsmartcard.CryptoUtils.crypto_checksum(self.current_SE.cct.algorithm,
@@ -1096,15 +1054,15 @@ class Secure_Messaging(object):
from Crypto.Util.randpool import RandomPool from Crypto.Util.randpool import RandomPool
rnd = RandomPool() rnd = RandomPool()
cipher = self.CAPDU_SE.ct.algorithm #FIXME: Current SE? cipher = self.current_SE.ct.algorithm
c_class = locals().get(cipher, None) c_class = locals().get(cipher, None)
if c_class is None: if c_class is None:
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"]) raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
if p1 & 0x01 == 0x00: #Generate key if p1 & 0x01 == 0x00: #Generate key
PublicKey = c_class.generate(self.CAPDU_SE.dst.keylength,rnd.get_bytes) PublicKey = c_class.generate(self.current_SE.dst.keylength,rnd.get_bytes)
self.CAPDU_SE.dst.key = PublicKey self.current_SE.dst.key = PublicKey
else: else:
pass #Read key pass #Read key
@@ -1161,7 +1119,7 @@ class CryptoflexSM(Secure_Messaging):
rnd = RandomPool() rnd = RandomPool()
PublicKey = RSA.generate(keylength,rnd.get_bytes) PublicKey = RSA.generate(keylength,rnd.get_bytes)
self.CAPDU_SE.dst.key = PublicKey self.current_SE.dst.key = PublicKey
e_in = struct.unpack("<i",data) e_in = struct.unpack("<i",data)
if e_in[0] != 65537: if e_in[0] != 65537:
@@ -1193,9 +1151,9 @@ class CryptoflexSM(Secure_Messaging):
class ePass_SM(Secure_Messaging): class ePass_SM(Secure_Messaging):
def __init__(self,MF,CAPDU_SE,RAPDU_SE,ssc=None): def __init__(self,MF,SE,ssc=None):
self.ssc = ssc self.ssc = ssc
Secure_Messaging.__init__(self, MF, CAPDU_SE, RAPDU_SE) Secure_Messaging.__init__(self, MF, SE)
def compute_cryptographic_checksum(self,p1,p2,data): def compute_cryptographic_checksum(self,p1,p2,data):
""" """
@@ -1207,12 +1165,12 @@ class ePass_SM(Secure_Messaging):
if p1 != 0x8E or p2 != 0x80: if p1 != 0x8E or p2 != 0x80:
raise SwError(SW["ERR_INCORRECTP1P2"]) raise SwError(SW["ERR_INCORRECTP1P2"])
#checksum = virtualsmartcard.CryptoUtils.calculate_MAC(self.CAPDU_SE.cct.key,data,self.CAPDU_SE.cct.iv) #checksum = virtualsmartcard.CryptoUtils.calculate_MAC(self.current_SE.cct.key,data,self.current_SE_SE.cct.iv)
self.ssc += 1 self.ssc += 1
checksum = virtualsmartcard.CryptoUtils.crypto_checksum(self.CAPDU_SE.cct.algorithm, checksum = virtualsmartcard.CryptoUtils.crypto_checksum(self.current_SE.cct.algorithm,
self.CAPDU_SE.cct.key, self.current_SE.cct.key,
data, data,
self.CAPDU_SE.cct.iv, self.current_SE.cct.iv,
self.ssc) self.ssc)
return SW["NORMAL"], checksum return SW["NORMAL"], checksum