def protect(self, apdu): """ Protect the apdu following the doc9303 specification """ cmdHeader = self._maskClassAndPad(apdu) do87 = b"" do97 = b"" tmp = "Concatenate CmdHeader" if (apdu.getData()): tmp += " and DO87" do87 = self._buildD087(apdu) if (apdu.getLe()): tmp += " and DO97" do97 = self._buildD097(apdu) M = cmdHeader + do87 + do97 self.log(tmp) self.log("\tM: " + binToHexRep(M)) self._ssc = self._incSSC() self.log("Compute MAC of M") self.log("\tIncrement SSC with 1") self.log("\t\tSSC: " + binToHexRep(self._ssc)) N = pad(self._ssc + M) self.log("\tConcateate SSC and M and add padding") self.log("\t\tN: " + binToHexRep(N)) CC = mac(self._ksmac, N) self.log("\tCompute MAC over N with KSmac") self.log("\t\tCC: " + binToHexRep(CC)) do8e = self._buildD08E(CC) size = str(len(do87) + len(do97) + len(do8e)) protectedAPDU = cmdHeader[:4] + intToBin( size) + do87 + do97 + do8e + hexToBin(0x00) self.log("Construct and send protected APDU") self.log("\tProtectedAPDU: " + binToHexRep(protectedAPDU)) return CommandAPDU(binToHexRep(protectedAPDU[0]), binToHexRep(protectedAPDU[1]), binToHexRep(protectedAPDU[2]), binToHexRep(protectedAPDU[3]), binToHexRep(protectedAPDU[4]), binToHexRep(protectedAPDU[5:-1]), binToHexRep(protectedAPDU[-1]))
def createMAC(self): try: m = iso9797.mac(hexRepToBin(self.field2Form.get()), iso9797.pad(hexRepToBin(self.field1Form.get()))) self.writeToLog( "MAC:\n message: {0}\n Key: {1}\n MAC: {2}".format( self.field1Form.get(), self.field2Form.get(), binToHexRep(m))) self.field1Form.delete(0, END) self.field2Form.delete(0, END) self.field1Form.insert(0, binToHexRep(m)) except Exception, msg: tkMessageBox.showerror("Error: BAC", str(msg))
def unprotect(self, rapdu): """ Unprotect the APDU following the iso7816 specification """ needCC = False do87 = b"" do87Data = None do99 = b"" do8e = b"" offset = 0 #Check for a SM error if (rapdu.sw1 != 0x90 or rapdu.sw2 != 0x00): return rapdu rapdu = rapdu.getBinAPDU() self.log(rapdu) self.log("Receive response APDU of MRTD's chip") self.log("\tRAPDU: " + binToHexRep(rapdu)) #DO'87' #Mandatory if data is returned, otherwise absent if rapdu[0] == 0x87: (encDataLength, o) = asn1Length(rapdu[1:]) offset = 1 + o if rapdu[offset] != 0x1: raise SecureMessagingException( "DO87 malformed, must be 87 L 01 <encdata> : " + binToHexRep(rapdu)) do87 = rapdu[0:offset + encDataLength] do87Data = rapdu[offset + 1:offset + encDataLength] offset += encDataLength needCC = True #DO'99' #Mandatory, only absent if SM error occurs do99 = rapdu[offset:offset + 4] sw1 = rapdu[offset + 2] sw2 = rapdu[offset + 3] offset += 4 needCC = True # removed hexRepToBin("9902"): if do99[0:2] != b"\x99\x02": #SM error, return the error code return ResponseAPDU([], sw1, sw2) self.log(rapdu[offset]) #DO'8E' #Mandatory if DO'87' and/or DO'99' is present if rapdu[offset] == 0x8E: ccLength = binToHex(rapdu[offset + 1]) CC = rapdu[offset + 2:offset + 2 + ccLength] do8e = rapdu[offset:offset + 2 + ccLength] #CheckCC tmp = "" if do87: tmp += " DO'87" if do99: tmp += " DO'99" self.log("Verify RAPDU CC by computing MAC of" + tmp) self._ssc = self._incSSC() self.log("\tIncrement SSC with 1") self.log("\t\tSSC: " + binToHexRep(self._ssc)) K = pad(self._ssc + do87 + do99) self.log("\tConcatenate SSC and" + tmp + " and add padding") self.log("\t\tK: " + binToHexRep(K)) self.log("\tCompute MAC with KSmac") CCb = mac(self._ksmac, K) self.log("\t\tCC: " + binToHexRep(CCb)) res = (CC == CCb) self.log("\tCompare CC with data of DO'8E of RAPDU") self.log("\t\t" + binToHexRep(CC) + " == " + binToHexRep(CCb) + " ? " + str(res)) if not res: raise SecureMessagingException( "Invalid checksum for the rapdu : " + str(binToHex(rapdu))) elif needCC: raise SecureMessagingException( "Mandatory id DO'87' and/or DO'99' is present") data = [] if (do87Data): #There is a payload tdes = DES3.new(self._ksenc, DES.MODE_CBC, b'\0' * 8) data = unpad(tdes.decrypt(do87Data)) self.log("Decrypt data of DO'87 with KSenc") self.log("\tDecryptedData: " + binToHexRep(data)) self.log("Unprotected APDU: [" + binToHexRep(data) + "] " + binToHexRep(sw1) + " " + binToHexRep(sw2)) return ResponseAPDU(data, binToHex(sw1), binToHex(sw2))