Esempio n. 1
0
 def unwrapResp(self, resp, sw1, sw2):
     """ Unwrap response (decipher and check MAC)."""
     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_RMAC:
         assert len(resp) >= 8, "Resp data shorter than 8: %d" % len(resp)
         data2sign = self.MACchain + dresp[:-8] + chr(sw1) + chr(sw2)
         rmac = CMAC(self.SRMAC, data2sign)[:8]
         assert rmac == dresp[-8:], "Wrong R-MAC: %s vs expected: %s" % \
             (hexlify(dresp[-8:]).upper(), hexlify(rmac).upper())
         dresp = dresp[:-8]
     if (self.SL | self.rmacSL) & SL_RENC and len(dresp) > 0:
         assert len(dresp) % 16 == 0, \
             "Length of encrypted data not multiple of 16: %d" % len(dresp)
         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)
         ddata = k.decrypt(dresp)
         data = unpad80(ddata, 16)
         assert len(data) > 0, "Empty data encrypted"
     else:
         data = dresp
     return s2l(data), sw1, sw2
Esempio n. 2
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
Esempio n. 3
0
  def _doDelete(self, aid, P2, token):
      """ Build delete APDU (either package or instance)
token        - instance of Token, calculates token for Delegated
               management if present"""
      data = '\x4F' + derLV(aid)
      if token:
          data += token.getCRT()
          data2sign = pack("BBB", 0, P2, len(data)) + data
          data += '\x9E' + derLV(token.calc(data2sign))
      apdu = [0x80, INS_DELETE, 0, P2, len(data)] + s2l(data)
      return apdu
Esempio n. 4
0
    def test_Cdecrypt(self):
        host_challenge = unhexlify('0807060504030201')
        scp = SCP03(**self.scp_par)
        apdu = scp.initUpdate(host_challenge)
        apdu = scp.extAuth(SL=3)

        apdu_i4lh = '80E60200150A45786572636973655236000006EF04C602068200'
        apdu_i4l = s2l(unhexlify(apdu_i4lh))
        wapdu = scp.wrapAPDU(apdu_i4l)
        encdata = l2s(wapdu[5:-8])
        self.assertEqual(encdata,
                         unhexlify('DF31907FC027482D5DCB7DC028245F7C108CA4D2AFF12275079768E1EFE9429E'))
Esempio n. 5
0
    def install_inst(self, token=None):
        """ Build Install for install APDU.
  token        - instance of Token, calculates token for Delegated
                 management if present"""
        privileges = getattr(self, 'privileges', '\0')
        sys_spec_par = ''.join(
            getattr(self, 'par_sys',
                    [unhexlify("C7020000"),
                     unhexlify("C8020000")]))
        if 'par_sys_sim' in self.__dict__:
            sys_spec_par += '\xCA' + derLV(self.par_sys_sim)
        sys_spec_par = '\xEF' + derLV(sys_spec_par)

        app_spec_par = 'par_applet' in self.__dict__ \
                       and self.par_applet or ''
        app_spec_par = '\xC9' + derLV(app_spec_par)

        uicc_spec = []
        if 'par_UICC_toolkit' in self.__dict__:
            uicc_spec.append('\x80' + derLV(self.par_UICC_toolkit))
        if 'par_UICC_DAP' in self.__dict__:
            uicc_spec.append('\xC3' + derLV(self.par_UICC_DAP))
        if 'par_UICC_access' in self.__dict__:
            uicc_spec.append('\x81' + derLV(self.par_UICC_access))
        if 'par_UICC_admin_access' in self.__dict__:
            uicc_spec.append('\x82' + derLV(self.par_UICC_admin_access))
        if uicc_spec:
            uicc_sys_par = '\xEA' + derLV(''.join(uicc_spec))
        else:
            uicc_sys_par = ''

        AID_inst = getattr(self, 'AID_instance', self.AID_module)

        params = app_spec_par + sys_spec_par + uicc_sys_par
        if token:
            params += token.getCRT()
        data = derLV(self.AID_package) + \
            derLV(self.AID_module) + \
            derLV(AID_inst) + \
            derLV(privileges) + \
            derLV(params)
        if token:
            data2sign = pack("BBB", P1_INST_INSMSEL, 0, len(data)) + data
            data += derLV(token.calc(data2sign))
        else:
            data += '\0'

        assert len(data) < 0x100, "Data longer than 0xFF: 0x%X '%s'" % \
            (len(data), hexlify(data).upper())

        apdu = [0x80, INS_INSTALL, P1_INST_INSMSEL, 0, len(data)] + s2l(data)
        return apdu
Esempio n. 6
0
 def send(self, templ, **kw):
     objects = self.objects.copy()
     objects.update(kw)
     sapdu = GAF(templ).eval(**objects)
     apdu = s2l(sapdu)
     assert 5 <= len(apdu) and len(apdu) <= 260, "Wrong APDU length %d, '%s'" % (len(apdu), hexlify(sapdu))
     resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
     if sw1 == 0x6C and len(apdu) == 5:
         apdu[4] = sw2
         resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
     elif sw1 == 0x61:
         apdu = [0, 0xC0, 0, 0, sw2]
         resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
     sw = (sw1 << 8) + sw2
     return l2s(resp), sw
Esempio n. 7
0
 def send( self, templ, **kw ):
     objects = self.objects.copy()
     objects.update( kw )
     sapdu = GAF( templ ).eval( **objects )
     apdu = s2l( sapdu )
     assert 5 <= len( apdu ) and len( apdu ) <= 260,\
         "Wrong APDU length %d, '%s'" % ( len(apdu), hexlify( sapdu ))
     resp, sw1, sw2 = CardConnectionDecorator.transmit( self, apdu )
     if sw1 == 0x6C and len( apdu ) == 5:
         apdu[4] = sw2
         resp, sw1, sw2 = CardConnectionDecorator.transmit( self, apdu )
     elif sw1 == 0x61:
         apdu = [ 0, 0xC0, 0, 0, sw2 ]
         resp, sw1, sw2 = CardConnectionDecorator.transmit( self, apdu )
     sw = ( sw1 << 8 ) + sw2
     return l2s( resp ), sw
Esempio n. 8
0
    def unwrapAPDU(self, SL):
        host_challenge = unhexlify('0807060504030201')
        scp = SCP03(**self.scp_par)
        apdu = scp.initUpdate(host_challenge)
        apdu = scp.extAuth(SL)
        macchain = scp.MACchain
        cmdCount = scp.cmdCount

        apdu_i4lh = '80E60200150A45786572636973655236000006EF04C602068200'
        apdu_i4l = s2l(unhexlify(apdu_i4lh))
        wapdu = scp.wrapAPDU(apdu_i4l)

        scp.MACchain = macchain
        scp.cmdCount = cmdCount
        papdu = scp.unwrapAPDU(wapdu)
        self.assertEqual(papdu, apdu_i4l)
Esempio n. 9
0
        def mut_auth(self, SL, **kw):
            """ Perform mutual authentication.
Optional paramters in kw:
logCh          - logical channel (u8, default 0)
host_challenge - string 8B long
aid            - AID to select (string, default self.scp)
                 (SD_AID for calculation is self.scp.SD_AID)
 """
            # select SD
            logCh = kw.get('logCh', 0)
            assert 0 <= logCh and logCh < 20
            self.scp.logCh = logCh
            aid = kw.get('aid', self.scp.SD_AID)
            assert 5 <= len(aid) and len(aid) <= 16
            cla = self.scp.CLA(False, b8=0)
            apdu = [cla, 0xA4, 0x04, 0, len(aid)] + s2l(aid)
            resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
            if sw1 == 0x61:
                apdu = [cla, 0xC0, 0, 0, sw2]
                resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
            sw = (sw1 << 8) + sw2
            if sw != 0x9000:
                raise ISOerror("NOK: SW = %04X", sw)

            # Initial update
            host_challenge = kw.get('host_challenge', '\0'*8)
            assert len(host_challenge) == 8
            apdu = self.scp.initUpdate(host_challenge, logCh)
            resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
            # Case 4 command, expects 61xx
            assert sw1 == 0x61
            resp, sw1, sw2 = self.getResponse(sw2)
            sw = (sw1 << 8) + sw2
            if sw != 0x9000:
                raise ISOerror("NOK: SW = %04X", sw)
            # check response to initial update, may raise exception
            self.scp.parseInitUpdateResp(resp)

            # External authenticate
            apdu = self.scp.extAuth(SL)
            resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
            sw = (sw1 << 8) + sw2
            if sw != 0x9000:
                raise ISOerror("NOK: SW = %04X", sw)
Esempio n. 10
0
    def send(self, templ, **kw):
        """ Evaluate GAF and transmit as APDU
templ   - a GAF template to evaluate
kw      - GAF dictionary (updates dictionary from SCP02Connection.__init__)
Return (resp, SW) as (str, int)"""
        objects = self.objects.copy()
        objects.update(kw)
        papdu = s2l(GAF(templ).eval(**objects))
        apdu = self.scp.wrapAPDU(papdu)
        resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
        if sw1 == 0x6C and len(papdu) == 5:
            papdu[4] = sw2
            apdu = self.scp.wrapAPDU(papdu)
            resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
        elif sw1 == 0x61:
            resp, sw1, sw2 = self.getResponse(sw2)
        resp, sw1, sw2 = self.scp.unwrapResp(resp, sw1, sw2)
        sw = (sw1 << 8) + sw2
        return l2s(resp), sw
Esempio n. 11
0
    def send(self, templ, **kw):
        """ Evaluate GAF and transmit as APDU
templ   - a GAF template to evaluate
kw      - GAF dictionary (updates dictionary from GAFConnection.__init__)
Return ( resp, SW ) as ( str, int )"""
        objects = self.objects.copy()
        objects.update(kw)
        sapdu = GAF(templ).eval(**objects)
        apdu = s2l(sapdu)
        assert 5 <= len( apdu ) and len( apdu ) <= 260,\
            "Wrong APDU length %d, '%s'" % ( len(apdu), hexlify( sapdu ))
        resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
        if sw1 == 0x6C and len(apdu) == 5:
            apdu[4] = sw2
            resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
        elif sw1 == 0x61:
            apdu = [0, 0xC0, 0, 0, sw2]
            resp, sw1, sw2 = CardConnectionDecorator.transmit(self, apdu)
        sw = (sw1 << 8) + sw2
        return l2s(resp), sw
Esempio n. 12
0
    def unwrapAPDU(self, apdu):
        """ Parse MACed/encrypted APDU, decipher and check MAC. """
        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
        assert cla & 0x04, "Secure messaging missing"
        if (cla & 0x40 == 0 and cla & 0x03 > 0) or cla & 0x40 != 0:
            # check logical channels
            assert cla == self.CLA(True, b8), "CLA mismatch"
        scla = b8 | 0x04  # CLA without log. ch. but with secure messaging

        data = l2s(apdu[5:])
        if self.SL & SL_CMAC:    # C-MAC
            assert lc >= 8, "Missing/ too short CMAC"
            sdata = data[:-8]
            data2sign = self.MACchain + chr(scla) + l2s(apdu[1:4])\
                + chr(lc) + sdata
            self.MACchain = CMAC(self.SMAC, data2sign)
            assert data[-8:] == self.MACchain[:8], "Wrong CMAC"
            data = sdata
            lc -= 8
        if self.SL & SL_CENC and lc > 0:  # C-ENC
            assert lc % 16 == 0, "Encoded data length not multiple of BS"
            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)
            pdata = k.decrypt(data)
            data = unpad80(pdata, 16)
            assert len(data) > 0, "Empty data encrypted"
            lc = len(data)
        apdu = [self.CLA(False, b8)] + apdu[1:4] + [lc] + s2l(data)
        return apdu
Esempio n. 13
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
Esempio n. 14
0
    def install_extradict(self, aid_sd, token=None):
        """ Build install for extradiction APDU
  aid_sd       - AID of SD to extradite to/from
  token        - instance of Token, calculates token for Delegated
                 management if present
 """
        assert 5 <= len(aid_sd) and len(aid_sd) <= 16
        AID_inst = getattr(self, 'AID_instance', self.AID_module)

        params = token and token.getCRT() or ''
        data = derLV(aid_sd) + '\0' + derLV(AID_inst) + '\0' + derLV(params)

        if token:
            data2sign = pack("BBB", P1_INST_EXTRA, 0, len(data)) + data
            data += derLV(token.calc(data2sign))
        else:
            data += '\0'
        assert len(data) < 0x100, "Data longer than 0xFF: 0x%X '%s'" % \
            (len(data), hexlify(data).upper())
        apdu = [0x80, INS_INSTALL, P1_INST_EXTRA, 0, len(data)] + s2l(data)
        return apdu
Esempio n. 15
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
Esempio n. 16
0
    def load(self, datalen=239, token=None, DAP=[], cipher=None, AID_SD=''):
        """ Build list of APDUs for InstallForLoad and Load.
  datalen      - data length in Load APDUs
  token        - instance of Token, calculates token for Delegated
                 management if present
  DAP          - list of (aid, signature_function). For each item, E2 TLV
                 is inserted (each signature_function called on LFDB hash).
                 Example of signature_function: DESsign.calc or RSAsign.calc
  cipher       - cipher function for Ciphere Load File Data Block
                 if present, D4#(cipher(<ijc content>)) sent instead of C4
  AID_SD       - AID of SD to load package to
"""
        f = open(self.file_ijc, "rb")
        ijc_data = f.read()
        ijc_len = len(ijc_data)
        h = hashlib.new('sha1')
        h.update(ijc_data)
        ijc_hash = h.digest()
        print "Loading '%s', len = %d, SHA1 = %s" % \
            (self.file_ijc, ijc_len, hexlify(ijc_hash).upper())

        # build Install for load APDU
        sysparams = ''.join(
            getattr(self, 'par_sysLoad', [
                unhexlify("C6020000"),
                unhexlify("C7020000"),
                unhexlify("C8020000")
            ]))
        params = '\xEF' + derLV(sysparams)
        if token:
            params += token.getCRT()

        # put ijc hash only if token or DAP is present
        ins_hash = (token is not None or len(DAP) > 0) and ijc_hash or ''
        data = derLV(self.AID_package) + \
            derLV(AID_SD) + \
            derLV(ins_hash) + \
            derLV(params)

        if token:
            data2sign = pack("BBB", P1_INST_LOAD, 0, len(data)) + data
            data += derLV(token.calc(data2sign))
        else:
            data += '\0'

        assert len(data) < 0x100, "Data longer than 0xFF: 0x%X '%s'" % \
            (len(data), hexlify(data).upper())
        apdus = [[0x80, INS_INSTALL, 2, 0, len(data)] + s2l(data)]

        # build Load APDUs GP CS 2.2.1 11.6.2.3
        load_data = ''
        E2template = GAF("E2 #(4F #($aid) C3 #($sig))")
        for d in DAP:
            sig = d[1](ijc_hash)  # calculate signature
            load_data += E2template.eval(aid=d[0], sig=sig)
        if cipher:
            load_data += '\xD4' + derLV(cipher(ijc_data))
        else:
            load_data += '\xC4' + derLV(ijc_data)

        napdu = (len(load_data) + datalen - 1) / datalen
        P1 = 0
        for i in xrange(napdu):
            if i == napdu - 1:  # the last block
                P1 = 0x80
                datalen = len(load_data)
            apdus.append([0x80, INS_LOAD, P1, i, datalen] +
                         s2l(load_data[:datalen]))
            load_data = load_data[datalen:]
        return apdus
Esempio n. 17
0
 def install_perso(self):
     """ Build install for perso APDU """
     AID_inst = getattr(self, 'AID_instance', self.AID_module)
     data = '\0\0' + derLV(AID_inst) + '\0\0\0'
     apdu = [0x80, INS_INSTALL, P1_INST_PERSO, 0, len(data)] + s2l(data)
     return apdu