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:
@@ -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,20 +576,14 @@ 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
|
||||||
|
|||||||
Reference in New Issue
Block a user