def external_authenticate(self, p1, p2, resp_data): """Performs the basic access control protocol as defined in the ICAO MRTD standard""" rnd_icc = self.last_challenge # Receive Mutual Authenticate APDU from terminal # Decrypt data and check MAC Eifd = resp_data[:-8] padded_Eifd = vsCrypto.append_padding(self.current_SE.cct.blocklength, Eifd) Mifd = vsCrypto.crypto_checksum("CC", self.KMac, padded_Eifd) # Check the MAC if not Mifd == resp_data[-8:]: raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"]) # Decrypt the data plain = vsCrypto.decrypt("DES3-CBC", self.KEnc, resp_data[:-8]) if plain[8:16] != rnd_icc: raise SwError(SW["WARN_NOINFO63"]) # Extract keying material from IFD, generate ICC keying material Kifd = plain[16:] rnd_ifd = plain[:8] Kicc = urandom(16) # Generate Answer data = plain[8:16] + plain[:8] + Kicc Eicc = vsCrypto.encrypt("DES3-CBC", self.KEnc, data) padded_Eicc = vsCrypto.append_padding(self.current_SE.cct.blocklength, Eicc) Micc = vsCrypto.crypto_checksum("CC", self.KMac, padded_Eicc) # Derive the final keys and set the current SE KSseed = vsCrypto.operation_on_string(Kicc, Kifd, lambda a, b: a ^ b) self.current_SE.ct.key = self.derive_key(KSseed, 1) self.current_SE.cct.key = self.derive_key(KSseed, 2) self.current_SE.ssc = stringtoint(rnd_icc[-4:] + rnd_ifd[-4:]) return SW["NORMAL"], Eicc + Micc
def verify_cryptographic_checksum(self, p1, p2, data): """ Verify the cryptographic checksum contained in the data field. Data field must contain a cryptographic checksum (tag 0x8E) and a plain value (tag 0x80) """ plain = "" cct = "" algo = self.cct.algorithm key = self.cct.key iv = self.cct.iv if algo == None or key == None: raise SwError(SW["ERR_CONDITIONNOTSATISFIED"]) structure = unpack(data) for tag, length, value in structure: if tag == 0x80: plain = value elif tag == 0x8E: cct = value if plain == "" or cct == "": raise SwError(SW["ERR_SECMESSOBJECTSMISSING"]) else: my_cct = vsCrypto.crypto_checksum(algo, key, plain, iv) if my_cct == cct: return "" else: raise SwError["ERR_SECMESSOBJECTSINCORRECT"]
def compute_cryptographic_checksum(self, p1, p2, data): """ Compute a cryptographic checksum (e.g. MAC) for the given data. Algorithm and key are specified in the current SE """ if p1 != 0x8E or p2 != 0x80: raise SwError(SW["ERR_INCORRECTP1P2"]) if self.cct.key is None: raise SwError(SW["ERR_CONDITIONNOTSATISFIED"]) checksum = vsCrypto.crypto_checksum(self.cct.algorithm, self.cct.key, data, self.cct.iv) return checksum
def compute_cryptographic_checksum(self, p1, p2, data): """ Compute a cryptographic checksum (e.g. MAC) for the given data. Algorithm and key are specified in the current SE """ if p1 != 0x8E or p2 != 0x80: raise SwError(SW["ERR_INCORRECTP1P2"]) if self.cct.key == None: raise SwError(SW["ERR_CONDITIONNOTSATISFIED"]) checksum = vsCrypto.crypto_checksum(self.cct.algorithm, self.cct.key, data, self.cct.iv) return checksum
def compute_cryptographic_checksum(self, p1, p2, data): """ Compute a cryptographic checksum (e.g. MAC) for the given data. The ePass uses a Send Sequence Counter for MAC calculation """ if p1 != 0x8E or p2 != 0x80: raise SwError(SW["ERR_INCORRECTP1P2"]) self.ssc += 1 checksum = vsCrypto.crypto_checksum(self.cct.algorithm, self.cct.key, data, self.cct.iv, self.ssc) return checksum