Пример #1
0
    def wrapAPDU(self, apdu):
        """ Wrap APDU for SCP02, i.e. calculate MAC and encrypt.
Input APDU and output APDU are list of uint8. """
        lc = len(apdu) - 5
        assert len(apdu) >= 5, "Wrong APDU length: %d" % len(apdu)
        assert len(apdu) == 5 or apdu[4] == lc, \
            "Lc differs from length of data: %d vs %d" % (apdu[4], lc)

        cla = apdu[0]
        b8 = cla & 0x80
        if cla & 0x03 > 0 or cla & 0x40 != 0:
            # nonzero logical channel in APDU, check that are the same
            assert cla == self.CLA(False, b8), "CLA mismatch"
        sapdu = l2s(apdu)
        # CLA without log. channel can be 80 or 00 only
        if self.isCMAC:
            if self.i & M_CMAC_MODIF:  # CMAC on unmodified APDU
                mlc = lc
                clac = chr(b8)
            else:  # CMAC on modified APDU
                mlc = lc + 8
                clac = chr(b8 + 0x04)
            mac = self.calcMAC_1d(clac + sapdu[1:4] + chr(mlc) + sapdu[5:])
            mac = [ord(x) for x in mac]
            if self.isENC:
                k = DES3.new(self.ses_ENC, DES.MODE_CBC, ZERO8)
                data = s2l(k.encrypt(pad80(sapdu[5:], 8)))
                lc = len(data)
            else:
                data = apdu[5:]
            lc += 8
            apdu = [self.CLA(True, b8)] + apdu[1:4] + [lc] + data + mac
        return apdu
Пример #2
0
 def wrapData(self, data, zPad=False):
     """ Cipher data by DEK. """
     if zPad:
         data = pad80(data)
     assert len(data) % 8 == 0, "Sensitive data must be BS padded"
     k = DES3.new(self.ses_DEK, DES.MODE_ECB)
     return k.encrypt(data)
Пример #3
0
    def wrapAPDU( self, apdu ):
        """ Wrap APDU for SCP02, i.e. calculate MAC and encrypt.
Input APDU and output APDU are list of uint8. """
        lc = len( apdu ) - 5
        assert len( apdu ) >= 5, "Wrong APDU length: %d" % len( apdu )
        assert len( apdu ) == 5 or apdu[4] == lc, \
           "Lc differs from length of data: %d vs %d" % ( apdu[4], lc )

        cla = apdu[0]
        b8 = cla & 0x80
        if cla & 0x03 > 0 or cla & 0x40 != 0:
            # nonzero logical channel in APDU, check that are the same
            assert cla == self.CLA( False, b8 ), "CLA mismatch"
        scla = b8 | 0x04  # CLA without log. ch. but with secure messaging
        sapdu = l2s( apdu )
        # CLA without log. channel can be 80 or 00 only
        if self.isCMAC:
            if self.i & M_CMAC_MODIF: # CMAC on unmodified APDU
                mlc = lc
                clac = chr( b8 )
            else:                     # CMAC on modified APDU
                mlc = lc + 8
                clac = chr( b8 + 0x04 )
            mac = self.calcMAC_1d( clac + sapdu[1:4] + chr(mlc) + sapdu[5:] )
            mac = [ ord(x) for x in mac ]
            if self.isENC:
                k = DES3.new( self.ses_ENC, DES.MODE_CBC, ZERO8 )
                data = [ ord(x) for x in k.encrypt( pad80( sapdu[5:] ))]
                lc = len( data )
            else:
                data = apdu[5:]
            lc += 8
            apdu = [ self.CLA( True, b8 )] + apdu[1:4] + [ lc ] + data + mac
        return apdu
Пример #4
0
 def calcMAC_3d(self, s):
     """ Pad string and calculate MAC according to B.1.2.1 - Full 3DES """
     e = DES3.new(self.ses_ENC, DES.MODE_ECB)
     s = pad80(s, 8)
     q = len(s) / 8
     h = ZERO8
     for i in xrange(q):
         h = e.encrypt(bxor(h, s[8 * i:8 * (i + 1)]))
     return h
Пример #5
0
 def calcMAC_3d( self, s ):
     """ Pad string and calculate MAC according to B.1.2.1 - Full 3DES """
     e = DES3.new( self.ses_ENC, DES.MODE_ECB )
     s = pad80( s )
     q = len( s ) / 8
     h = ZERO8
     for i in xrange(q):
         h = e.encrypt( bxor( h, s[8*i:8*(i+1)] ))
     return h
Пример #6
0
 def calc(self, s):
     " Pad string and calculate MAC according to B.1.2.2 - " +\
         "Single DES plus final 3DES """
     s = pad80(s, 8)
     q = len(s) / 8
     h = '\0' * 8  # zero ICV
     for i in xrange(q):
         h = self.e.encrypt(bxor(h, s[8 * i:8 * (i + 1)]))
     h = self.d.decrypt(h)
     h = self.e.encrypt(h)
     return h
Пример #7
0
 def calcMAC_1d(self, s, zResetICV=False):
     " Pad string and calculate MAC according to B.1.2.2 - " +\
         "Single DES plus final 3DES """
     e = DES.new(self.ses_C_MAC[:8], DES.MODE_ECB)
     d = DES.new(self.ses_C_MAC[8:], DES.MODE_ECB)
     s = pad80(s, 8)
     q = len(s) / 8
     h = zResetICV and ZERO8 or self.icv
     for i in xrange(q):
         h = e.encrypt(bxor(h, s[8 * i:8 * (i + 1)]))
     h = d.decrypt(h)
     h = e.encrypt(h)
     self.icv = (self.i & M_ICV_ENC) and self.k_icv.encrypt(h) or h
     return h
Пример #8
0
 def calcMAC_1d( self, s, zResetICV = False ):
     " Pad string and calculate MAC according to B.1.2.2 - " +\
         "Single DES plus final 3DES """
     e = DES.new( self.ses_C_MAC[:8], DES.MODE_ECB )
     d = DES.new( self.ses_C_MAC[8:], DES.MODE_ECB )
     s = pad80( s )
     q = len( s ) / 8
     h = zResetICV and ZERO8 or self.icv
     for i in xrange(q):
         h = e.encrypt( bxor( h, s[8*i:8*(i+1)] ))
     h = d.decrypt( h )
     h = e.encrypt( h )
     self.icv = ( self.i & M_ICV_ENC ) and self.k_icv.encrypt( h ) or h
     return h
Пример #9
0
 def wrapResp(self, resp, sw1, sw2):
     """ Wrap expected response as card would do."""
     sw = (sw1 << 8) + sw2
     if not(sw == 0x9000 or sw1 in (0x62, 0x63)):
         assert len(resp) == 0, "No response data expected"
         return [], sw1, sw2
     dresp = l2s(resp)
     if (self.SL | self.rmacSL) & SL_RENC and len(dresp) > 0:
         assert len(dresp) <= 0xEF, "Data too long for RENC+RMAC"
         k = AES.new(self.SENC, AES.MODE_ECB)
         ICV = k.encrypt(pack(">QQ", 0x8000000000000000L |
                              self.cmdCount / 0x10000000000000000L,
                              self.cmdCount % 0x10000000000000000L))
         k = AES.new(self.SENC, AES.MODE_CBC, IV=ICV)
         dresp = k.encrypt(pad80(dresp, 16))
     if (self.SL | self.rmacSL) & SL_RMAC:
         assert len(dresp) <= 0xF0, "Data too long for RMAC"
         data2sign = self.MACchain + dresp + chr(sw1) + chr(sw2)
         rmac = CMAC(self.SRMAC, data2sign)[:8]
         dresp += rmac
     return s2l(dresp), sw1, sw2
Пример #10
0
    def wrapAPDU(self, apdu):
        """ Wrap APDU for SCP03, i.e. calculate MAC and encrypt.
Input APDU and output APDU are list of u8. """
        lc = self.checkAPDU(apdu)
        if apdu[1] == 0xC0:  # Get Response TPDU
            return apdu
        if 'beginRmaSL' in self.__dict__:
            self.rmacSL = self.beginRmacSL
            del self.beginRmacSL

        self.cmdCount += 1
        cla = apdu[0]
        b8 = cla & 0x80
        if (cla & 0x40 == 0 and cla & 0x03 > 0) or cla & 0x40 != 0:
            # check logical channels
            assert cla == self.CLA(False, b8), "CLA mismatch"
        scla = b8 | 0x04  # CLA without log. ch. but with secure messaging
        cdata = l2s(apdu[5:])
        if self.SL & SL_CENC and lc > 0:  # C-ENC
            k = AES.new(self.SENC, AES.MODE_ECB)
            ICV = k.encrypt(
                pack(">QQ", self.cmdCount / 0x10000000000000000L,
                     self.cmdCount % 0x10000000000000000L))
            k = AES.new(self.SENC, AES.MODE_CBC, IV=ICV)
            data2enc = pad80(cdata, 16)
            cdata = k.encrypt(data2enc)
            lc = len(cdata)
        if self.SL & SL_CMAC:  # C-MAC
            lc += 8
            data2sign = self.MACchain + chr(scla) + l2s(apdu[1:4])
            if (lc > 0xff):
                data2sign += b'\x00' + chr((lc >> 8) & 0xff) + chr(lc & 0xff)
            else:
                data2sign += chr(lc)
            data2sign += cdata
            self.MACchain = CMAC(self.SMAC, data2sign)
            cdata += self.MACchain[:8]
        apdu = [self.CLA(True, b8)] + apdu[1:4] + [lc] + s2l(cdata)
        return apdu
Пример #11
0
 def wrapData( self, data, zPad = False ):
     """ Cipher data by DEK. """
     if zPad: data = pad80( data )
     assert len( data ) % 8 == 0, "Sensitive data must be BS padded"
     k = DES3.new( self.ses_DEK, DES.MODE_ECB )
     return k.encrypt( data )