Ejemplo n.º 1
0
 def _check_rand(self, rand):
     """Check provided rand and calculate temp. Use stored values if None"""
     if self.rand is None or rand is not None:
         self.rand = s2int(randomBytes(16)) if rand is None else \
                     self._check_int(rand, "RAND", 128)
         temp = self.Ek.encrypt(int2s(self.rand ^ self.OPc, 128))
         self.temp = s2int(temp)
Ejemplo n.º 2
0
 def calculate(self, ki, rand, op, sqn, amf, opc, mac_a, mac_s, res, ck, ik,
               ak_a, ak_s):
     m = MilenageAlgo(ki, op=op)
     self.assertEqual(m.OPc, s2int(opc), "Wrong OPc")
     mac = m.f1(rand, sqn, amf)
     self.assertEqual(mac[0], mac_a, "Wrong MAC_A")
     self.assertEqual(mac[1], mac_s, "Wrong MAC_A")
     self.assertEqual(m.f2(), res, "Wrong RES")
     self.assertEqual(m.f3(), ck, "Wrong CK")
     self.assertEqual(m.f4(), ik, "Wrong IK")
     self.assertEqual(m.f5(), s2int(ak_a), "Wrong AK auth")
     self.assertEqual(m.f5s(), s2int(ak_s), "Wrong AK resync")
Ejemplo n.º 3
0
    def parseInitUpdateResp(self, resp):
        """ Parse response to Init Update and if correct set diverData,
seqCounter, and card_challenge from it.
resp     - response (list[u8])
Raise exception in case of wrong response. """
        assert len(resp) in (29, 32), \
            "Wrong length of response data to Init Update: %d" % len(resp)
        diverData, keyInfo, card_chal, card_cryptogram, seqCounter =\
            partition(l2s(resp), (10, 13, 21, 29))
        kv, i = ord(keyInfo[0]), ord(keyInfo[2])
        assert 0x30 <= kv and kv <= 0x3F, \
            "Wrong key version in resp. to Init Update %02X" % kv
        assert keyInfo[1] == chr(0x03), \
            "Wrong SCP number in resp. to Init Update %02X" % ord(keyInfo[0])
        assert i & ~(M_PSEUDO | M_RMACENC) == 0 \
            and i != M_RMACENC ^ M_RMAC, "Wrong SCP03 parameter %02X" % i
        self.i, self.keyVer, self.diverData = i, kv, diverData

        if self.i & M_PSEUDO:
            assert len(seqCounter) == 3, "Missing seq. counter"
            self.seqCounter = s2int(seqCounter)
        else:
            assert len(seqCounter) == 0, "Seq. counter shall not be present"

        self.deriveKeys(card_chal)
        assert card_cryptogram == self.card_cryptogram, \
            "Recieved and calculated card cryptogram difer: %s vs. %s" % \
            (hexlify(card_cryptogram), hexlify(self.card_cryptogram))
Ejemplo n.º 4
0
 def _check_int(self, param, label, bitlen):
     """Convert param to int and check its value"""
     if isinstance(param, str):
         param = s2int(param)
     assert isinstance(param, int) or isinstance(param, long), \
         "Wrong type of " + label
     assert 0 <= param < (1 << bitlen), "Wrong value of " + label
     return param
Ejemplo n.º 5
0
    def f5s(self, rand=None):
        """Calculate anonimity keys for resync.
rand - str or int, if None, use the stored value
return AK as 48b integer"""
        self._check_rand(rand)
        arg = rot(self.temp ^ self.OPc, self.R[5]) ^ self.C[5]
        out5 = s2int(self.Ek.encrypt(int2s(arg, 128))) ^ self.OPc
        return out5 >> 80
Ejemplo n.º 6
0
    def f5(self, rand=None):
        """Calculate anonimity keys for authentication.
rand - str or int, if None, use the stored value
return AK as 48b integer"""
        self._check_rand(rand)
        arg = rot(self.temp ^ self.OPc, self.R[2]) ^ self.C[2]
        out2 = s2int(self.Ek.encrypt(int2s(arg, 128))) ^ self.OPc
        return out2 >> 80
Ejemplo n.º 7
0
    def f4(self, rand=None):
        """Calculate integrity key.
rand - str or int, if None, use the stored value
return IK as 16B str"""
        self._check_rand(rand)
        arg = rot(self.temp ^ self.OPc, self.R[4]) ^ self.C[4]
        out4 = s2int(self.Ek.encrypt(int2s(arg, 128))) ^ self.OPc
        return int2s(out4, 128)
Ejemplo n.º 8
0
    def f3(self, rand=None):
        """Calculate confidentiality key.
rand - str or int, if None, use the stored value
return CK as 16B str"""
        self._check_rand(rand)
        arg = rot(self.temp ^ self.OPc, self.R[3]) ^ self.C[3]
        out3 = s2int(self.Ek.encrypt(int2s(arg, 128))) ^ self.OPc
        return int2s(out3, 128)
Ejemplo n.º 9
0
    def __init__(self,
                 ki,
                 opc=None,
                 op=None,
                 c=(0, 1, 2, 4, 8),
                 r=(64, 0, 32, 64, 96)):
        """Initialization with key, OP(C) and Milenage parameters
ki, opc, op - strings of len 16B or int/long
c, r - 5-tuple of ints"""
        ki = self._check_str(ki, "KI")
        # encryption function
        self.Ek = AES.new(ki, AES.MODE_ECB)

        assert opc is not None or op is not None, \
            "Either OP or OPC must be specified"

        if opc is not None:
            self.OPc = self._check_int(opc, "OPC", 128)

        if op is not None:
            op = self._check_str(op, "OP")
            op_int = s2int(op)
            topc = s2int(self.Ek.encrypt(op)) ^ op_int
            if opc is None:
                self.OPc = topc
            else:
                assert topc == opc, "OPC %s does not match to KI, OPC: %s"

        # sanity check of c & r
        assert isinstance(c, tuple) or isinstance(c, list), "Wrong type of C"
        assert isinstance(r, tuple) or isinstance(r, list), "Wrong type of R"
        assert len(c) == 5, "Wrong number of parameters C"
        assert len(r) == 5, "Wrong number of parameters R"
        assert all([isinstance(ci, int) or isinstance(ci, long)
                    for ci in c]), "Wrong type of Ci"
        assert all([isinstance(ri, int) or isinstance(ri, long)
                    for ri in r]), "Wrong type of Ri"
        assert all([0 <= ci <= MASK128 for ci in c]), "Wrong value of Ci"
        assert all([0 <= ri < 128 for ri in r]), "Wrong value of Ri"
        self.C = tuple([None] + list(c))  # parameters are numbered from 1 to 5
        self.R = tuple([None] + list(r))
        self.rand = None
        self.temp = None
        self.sqn = (1 << 5) | 1
        self.amf = 0x0000
Ejemplo n.º 10
0
    def f2(self, rand=None):
        """Calculate authentication response.
rand - str or int, if None, use the stored value
return RES as 8B str"""
        self._check_rand(rand)
        arg = rot(self.temp ^ self.OPc, self.R[2]) ^ self.C[2]
        out2 = s2int(self.Ek.encrypt(int2s(arg, 128))) ^ self.OPc
        out2s = int2s(out2, 128)
        return out2s[8:]
Ejemplo n.º 11
0
def getExtCardRes( c ):
    """ Issue GET DATA with tag FF21 in order to receive Extended
Card Resources (GP 2.2.1, 11.3 & ETSI TS 102.226, 8.2.1.7).
Returns [ num. of install applets, free NVM, free RAM ]"""
    # CLA = 0x00: return only value
    # CLA = 0x80: return TLV, i.e. 0xFF21 #( value )
    apdu = [ 0x80, INS_GETDATA, 0xFF, 0x21, 0 ] 
    resp, sw1, sw2 = c.transmit( apdu )
    if sw1 == 0x6C:
        apdu[4] = sw2
        resp, sw1, sw2 = c.transmit( apdu )
    sw = ( sw1 << 8 ) + sw2
    if sw != 0x9000: raise ISOException( sw )
    payload = l2s( resp )
    result = [ s2int( findTLValue( payload, ( 0xFF21, tag ))) for
               tag in ( 0x81, 0x82, 0x83 )]
    return result
Ejemplo n.º 12
0
def getExtCardRes(c):
    """ Issue GET DATA with tag FF21 in order to receive Extended
Card Resources (GP 2.2.1, 11.3 & ETSI TS 102.226, 8.2.1.7).
Returns [ num. of install applets, free NVM, free RAM ]"""
    # CLA = 0x00: return only value
    # CLA = 0x80: return TLV, i.e. 0xFF21 #( value )
    apdu = [0x80, INS_GETDATA, 0xFF, 0x21, 0]
    resp, sw1, sw2 = c.transmit(apdu)
    if sw1 == 0x6C:
        apdu[4] = sw2
        resp, sw1, sw2 = c.transmit(apdu)
    sw = (sw1 << 8) + sw2
    if sw != 0x9000: raise ISOException(sw)
    payload = l2s(resp)
    result = [
        s2int(findTLValue(payload, (0xFF21, tag)))
        for tag in (0x81, 0x82, 0x83)
    ]
    return result
Ejemplo n.º 13
0
    def f1(self, rand=None, sqn=None, amf=None):
        """Calculate network & resync authentication code.
rand, sqn, amf - str or int, if None, use the stored value
return (MAC-A, MAC-S) as two 8B str"""
        self._check_rand(rand)
        if sqn is None:
            assert self.sqn is not None, "SQN not stored"
        else:
            self.sqn = self._check_int(sqn, "SQN", 48)
        if amf is None:
            assert self.amf is not None, "AMF not stored"
        else:
            self.amf = self._check_int(amf, "AMF", 16)
        in1 = (self.sqn << 16) | self.amf
        in1 |= in1 << 64

        arg = self.temp ^ rot(in1 ^ self.OPc, self.R[1]) ^ self.C[1]
        out1 = s2int(self.Ek.encrypt(int2s(arg, 128))) ^ self.OPc
        out1s = int2s(out1, 128)
        return out1s[:8], out1s[8:]
Ejemplo n.º 14
0
def cardInfo( c ):
    """Deselect, read EF_DIR, EF_ICCID"""
    resetCard( c )
    histBytes = l2s( ATR( c.getATR()).getHistoricalBytes())
    infoMF = selectFile( c, '' )
    # read EF_ICCID
    infoICCID = selectFile( c, unhexlify( '2FE2' ))
    fileSize = s2int( findTLValue( infoICCID, ( 0x62, 0x80 )))
    assert fileSize == 10, "Wrong size of EF_ICCID"
    iccid = swapNibbles( readBinary( c, fileSize ))
    # read EF_DIR
    infoDIR = selectFile( c, unhexlify( '2F00' ))
    # see ETSI 102.221 11.1.1.4.3 for coding
    fileDesc = findTLValue( infoDIR, ( 0x62, 0x82 ))
    assert len( fileDesc ) == 5 and \
        fileDesc[:2] == '\x42\x21' # linear EF
    recLen, nRec = unpack( ">HB", fileDesc[2:5] )
    dirDO = []
    for recNum in xrange( 1, nRec+1 ):
        try:
            r = readRecord( c, recNum )
            if r == '\xFF'* len( r ): continue
            aid = findTLValue( r, ( 0x61, 0x4F ))
            label = findTLValue( r, ( 0x61, 0x50 ))
            dirDO.append( { 'AID': aid,
                            'label': label } )
        except ISOException:
            break
    # select USIM and try to read IMSI
    if len( dirDO ) == 1:
        aid_usim = dirDO[0]['AID']
    else:
        aids = [ DO['AID'] for DO in dirDO
                 if re.match( DO['label'], 'USIM' )]
        if len( aids ) == 1:
            aid_usim = aids[0]
        else:
            aid_usim = None
    if aid_usim:
        infoUSIM = selectApplet( c, aid_usim )
        infoIMSI = selectFile( c, unhexlify( '7FFF6F07' ))
        try:
            bimsi = readBinary( c, 9 )
            digits = reduce( lambda d, n: d + [ ord(n) & 0x0F, ord(n) >> 4 ],
                             bimsi[ 1:1+ord(bimsi[0])], [] )
            digits.pop(0)          # remove first nibble 8 or 9
            while digits[-1] == 0x0F: digits.pop() # remove trailing F
            imsi = ''.join( [ chr(ord('0')+i) for i in digits ])
        except ISOException:
            imsi = None
    else: imsi = None
    # select default applet and get tags 45 and 42
    selectApplet( c, '' )
    try:
        cin = findTLValue( getData( c, 0x42 ), ( 0x42, ))
    except ISOException:
        cin = None
    try:
        iin = findTLValue( getData( c, 0x45 ), ( 0x45, ))
    except ISOException:
        iin = None
    return histBytes, iccid, dirDO, imsi, iin, cin
Ejemplo n.º 15
0
def cardInfo(c):
    """Deselect, read EF_DIR, EF_ICCID"""
    resetCard(c)
    histBytes = l2s(ATR(c.getATR()).getHistoricalBytes())
    infoMF = selectFile(c, '')
    # read EF_ICCID
    infoICCID = selectFile(c, unhexlify('2FE2'))
    fileSize = s2int(findTLValue(infoICCID, (0x62, 0x80)))
    assert fileSize == 10, "Wrong size of EF_ICCID"
    iccid = swapNibbles(readBinary(c, fileSize))
    # read EF_DIR
    infoDIR = selectFile(c, unhexlify('2F00'))
    # see ETSI 102.221 11.1.1.4.3 for coding
    fileDesc = findTLValue(infoDIR, (0x62, 0x82))
    assert len( fileDesc ) == 5 and \
        fileDesc[:2] == '\x42\x21' # linear EF
    recLen, nRec = unpack(">HB", fileDesc[2:5])
    dirDO = []
    for recNum in xrange(1, nRec + 1):
        try:
            r = readRecord(c, recNum)
            if r == '\xFF' * len(r): continue
            aid = findTLValue(r, (0x61, 0x4F))
            label = findTLValue(r, (0x61, 0x50))
            dirDO.append({'AID': aid, 'label': label})
        except ISOException:
            break
    # select USIM and try to read IMSI
    if len(dirDO) == 1:
        aid_usim = dirDO[0]['AID']
    else:
        aids = [DO['AID'] for DO in dirDO if re.match(DO['label'], 'USIM')]
        if len(aids) == 1:
            aid_usim = aids[0]
        else:
            aid_usim = None
    if aid_usim:
        infoUSIM = selectApplet(c, aid_usim)
        infoIMSI = selectFile(c, unhexlify('7FFF6F07'))
        try:
            bimsi = readBinary(c, 9)
            digits = reduce(
                lambda d, n: d + [ord(n) & 0x0F, ord(n) >> 4],
                bimsi[1:1 + ord(bimsi[0])], [])
            digits.pop(0)  # remove first nibble 8 or 9
            while digits[-1] == 0x0F:
                digits.pop()  # remove trailing F
            imsi = ''.join([chr(ord('0') + i) for i in digits])
        except ISOException:
            imsi = None
    else:
        imsi = None
    # select default applet and get tags 45 and 42
    selectApplet(c, '')
    try:
        cin = findTLValue(getData(c, 0x42), (0x42, ))
    except ISOException:
        cin = None
    try:
        iin = findTLValue(getData(c, 0x45), (0x45, ))
    except ISOException:
        iin = None
    return histBytes, iccid, dirDO, imsi, iin, cin