From d9f16f5a69b7064a9320e12d62df1e43737fa91e Mon Sep 17 00:00:00 2001 From: oepen Date: Fri, 29 Jul 2011 14:15:10 +0000 Subject: [PATCH] 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 --- .../vpicc/virtualsmartcard/SmartcardSAM.py | 116 ++++++------------ 1 file changed, 37 insertions(+), 79 deletions(-) diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/SmartcardSAM.py b/virtualsmartcard/src/vpicc/virtualsmartcard/SmartcardSAM.py index 2cf769a..44a2d88 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/SmartcardSAM.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/SmartcardSAM.py @@ -427,10 +427,8 @@ class PassportSAM(SAM): #SAM.__init__(self, path, key,None) SAM.__init__(self, None, None, mf) self.SM_handler = ePass_SM(mf, None, None, None) - self.SM_handler.CAPDU_SE.cct.algorithm = "CC" - self.SM_handler.RAPDU_SE.cct.algorithm = "CC" - self.SM_handler.CAPDU_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.current_SE.ct.algorithm = "DES3-CBC" def __computeKeys(self): """Computes the keys depending on the machine readable @@ -487,15 +485,11 @@ class PassportSAM(SAM): self.KSmac = self.derive_key(KSseed, 2) #self.ssc = rnd_icc[-4:] + rnd_ifd[-4:] #Set the current SE - self.SM_handler.CAPDU_SE.ct.key = self.KSenc - self.SM_handler.CAPDU_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.current_SE.ct.key = self.KSenc + self.SM_handler.current_SE.cct.key = self.KSmac self.SM_handler.ssc = stringtoint(rnd_icc[-4:] + rnd_ifd[-4:]) - self.SM_handler.CAPDU_SE.ct.algorithm = "DES3-CBC" - self.SM_handler.RAPDU_SE.ct.algorithm = "DES3-CBC" - self.SM_handler.CAPDU_SE.cct.algorithm = "CC" - self.SM_handler.RAPDU_SE.cct.algorithm = "CC" + self.SM_handler.current_SE.ct.algorithm = "DES3-CBC" + self.SM_handler.current_SE.cct.algorithm = "CC" return SW["NORMAL"], Eicc + Micc def _mac(self, key, data, ssc = None, dopad=True): @@ -557,6 +551,10 @@ class Security_Environment(object): self.dst = CRT(TEMPLATE_DST) 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): structure = TLVutils.unpack(config) @@ -578,21 +576,15 @@ class Security_Environment(object): class Secure_Messaging(object): - def __init__(self,MF,CAPDU_SE=None,RAPDU_SE=None): + def __init__(self,MF,SE=None): import virtualsmartcard.CryptoUtils self.mf = MF - if not CAPDU_SE: - self.CAPDU_SE = Security_Environment() + if not SE: + self.current_SE = Security_Environment() else: - self.CAPDU_SE = CAPDU_SE - if not RAPDU_SE: - self.RAPDU_SE = Security_Environment() - else: - self.RAPDU_SE = RAPDU_SE - - self.current_SE = Security_Environment() - + self.current_SE = SE + def set_MF(self,mf): self.mf = mf @@ -620,13 +612,13 @@ class Secure_Messaging(object): se = p1 >> 4 if(cmd == 0x01): 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 - self.current_SE = self.RAPDU_SE + self.current_SE.rapdu_sm = True 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 - pass + self.current_SE.external_auth = True self.__set_SE(p2,data) elif(cmd== 0x02): self.__store_SE(p2) @@ -664,7 +656,7 @@ class Secure_Messaging(object): Stores the current Security environment in the secure access module. The SEID is used as a reference to identify the SE. """ - SEstr = dumps(self.CAPDU_SE) + SEstr = dumps(self.current_SE) try: self.SAM.addkey(SEID, SEstr) #TODO: Need SAM reference except ValueError: @@ -679,9 +671,9 @@ class Secure_Messaging(object): SEstr = self.SAM.get_key(SEID) SE = loads(SEstr) if isinstance(SE, SecurityEnvironment): - self.CAPDU_SE = SE + self.current_SE = SE else: - raise ValueError + raise SwError(SW["ERR_REFNOTUSABLE"]) def __erase_SE(self,SEID): """ @@ -690,23 +682,6 @@ class Secure_Messaging(object): self.SAM.removeKey(SEID) 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. 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:]) if sw != 0x9000: 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) #SM data objects for authentication @@ -838,23 +813,6 @@ class Secure_Messaging(object): return c 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 It returns the protected data and the SW bytes @@ -878,15 +836,15 @@ class Secure_Messaging(object): return_data += encrypted_tlv if sw == SW["NORMAL"]: - if self.CAPDU_SE.cct.algorithm == None: + if self.current_SE.cct.algorithm == None: raise SwError(SW["CONDITIONSNOTSATISFIED"]) - elif self.CAPDU_SE.cct.algorithm == "CCT": + elif self.current_SE.cct.algorithm == "CCT": tag = SM_Class["CHECKSUM"] to_auth = virtualsmartcard.CryptoUtils.append_padding("DES-ECB", return_data) sw, auth = self.compute_cryptographic_checksum(0x8E, 0x80, to_auth) length = len(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"] hash = self.hash(0x90, 0x80, return_data) sw, auth = self.compute_digital_signature(0x9E, 0x9A, hash) @@ -938,7 +896,7 @@ class Secure_Messaging(object): """ if p1 != 0x8E or p2 != 0x80: 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"]) checksum = virtualsmartcard.CryptoUtils.crypto_checksum(self.current_SE.cct.algorithm, @@ -1096,15 +1054,15 @@ class Secure_Messaging(object): from Crypto.Util.randpool import RandomPool rnd = RandomPool() - cipher = self.CAPDU_SE.ct.algorithm #FIXME: Current SE? + cipher = self.current_SE.ct.algorithm c_class = locals().get(cipher, None) if c_class is None: raise SwError(SW["ERR_CONDITIONNOTSATISFIED"]) if p1 & 0x01 == 0x00: #Generate key - PublicKey = c_class.generate(self.CAPDU_SE.dst.keylength,rnd.get_bytes) - self.CAPDU_SE.dst.key = PublicKey + PublicKey = c_class.generate(self.current_SE.dst.keylength,rnd.get_bytes) + self.current_SE.dst.key = PublicKey else: pass #Read key @@ -1161,7 +1119,7 @@ class CryptoflexSM(Secure_Messaging): rnd = RandomPool() PublicKey = RSA.generate(keylength,rnd.get_bytes) - self.CAPDU_SE.dst.key = PublicKey + self.current_SE.dst.key = PublicKey e_in = struct.unpack("