def __init__(self, cardConnectionComponent): """Construct a new remote card connection. connection: the reader connection """ Pyro.core.ObjBase.__init__(self) CardConnectionDecorator.__init__(self, cardConnectionComponent)
def mut_auth(self, SL, logCh=0, **kw): """ Perform mutual authentication. Optional paramters in kw: - host_challenge """ # select SD self.scp.logCh = logCh aid = self.scp.SD_AID cla = self.scp.CLA(False, 0) apdu = [ cla, 0xA4, 0x04, 0, len( aid ) ] + \ [ ord( x ) for x in 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 ISOException(sw) # Initial update host_challenge = kw.get('host_challenge', '\0' * 8) apdu = self.scp.initUpdate(host_challenge, logCh) 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 ISOException(sw) # parse response to initial update in order to derive keys 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 ISOException(sw)
def connect(self, protocol=None, mode=None, disposition=None): '''Disconnect and reconnect in exclusive mode PCSCCardconnections.''' CardConnectionDecorator.connect(self, protocol, mode, disposition) component = self.component while True: if isinstance( component, smartcard.pcsc.PCSCCardConnection.PCSCCardConnection): pcscprotocol = PCSCCardConnection.translateprotocolmask( protocol) if 0 == pcscprotocol: pcscprotocol = component.getProtocol() if None != component.hcard: hresult = SCardDisconnect(component.hcard, SCARD_LEAVE_CARD) if hresult != 0: raise CardConnectionException('Failed to disconnect: ' + SCardGetErrorMessage(hresult)) hresult, component.hcard, dwActiveProtocol = SCardConnect( component.hcontext, str(component.reader), SCARD_SHARE_EXCLUSIVE, pcscprotocol) if hresult != 0: raise CardConnectionException( 'Failed to connect with SCARD_SHARE_EXCLUSIVE' +\ SCardGetErrorMessage(hresult)) # print('reconnected exclusive') break if hasattr(component, 'component'): component = component.component else: break
def mut_auth( self, SL, logCh = 0, **kw ): """ Perform mutual authentication. Optional paramters in kw: - host_challenge """ # select SD self.scp.logCh = logCh aid = self.scp.SD_AID cla = self.scp.CLA( False, 0 ) apdu = [ cla, 0xA4, 0x04, 0, len( aid ) ] + \ [ ord( x ) for x in 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 ISOException( sw ) # Initial update host_challenge = kw.get( 'host_challenge', '\0'*8 ) apdu = self.scp.initUpdate( host_challenge, logCh ) 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 ISOException( sw ) # parse response to initial update in order to derive keys 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 ISOException( sw )
def read_sector(connection: CardConnectionDecorator, sector_num: int): COMMAND = [ 0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, sector_num * 4, 0x60, 0x00 ] data, sw1, sw2 = connection.transmit(COMMAND) if (sw1, sw2) == (0x90, 0x0): pass elif (sw1, sw2) == (0x63, 0x0): COMMAND[8] = 0x61 data, sw1, sw2 = connection.transmit(COMMAND) if (sw1, sw2) == (0x90, 0x0): pass else: return False sector_data = b"" for block in range(sector_num * 4, sector_num * 4 + 4): COMMAND = [0xFF, 0xB0, 0x00] COMMAND.append(block) COMMAND.append(16) data, sw1, sw2 = connection.transmit(COMMAND) sector_data += bytes(data) print((sw1, sw2)) if (sw1, sw2) == (0x90, 0x0): return sector_data else: return False
def connect(self, protocol=None, mode=None, disposition=None): '''Disconnect and reconnect in exclusive mode PCSCCardconnections.''' CardConnectionDecorator.connect(self, protocol, mode, disposition) component = self.component while True: if isinstance( component, smartcard.pcsc.PCSCCardConnection.PCSCCardConnection): pcscprotocol = PCSCCardConnection.translateprotocolmask( protocol) if 0 == pcscprotocol: pcscprotocol = component.getProtocol() if component.hcard is not None: hresult = SCardDisconnect(component.hcard, SCARD_LEAVE_CARD) if hresult != 0: raise CardConnectionException( 'Failed to disconnect: ' + SCardGetErrorMessage(hresult)) hresult, component.hcard, dwActiveProtocol = SCardConnect( component.hcontext, str(component.reader), SCARD_SHARE_EXCLUSIVE, pcscprotocol) if hresult != 0: raise CardConnectionException( 'Failed to connect with SCARD_SHARE_EXCLUSIVE' + SCardGetErrorMessage(hresult)) # print('reconnected exclusive') break if hasattr(component, 'component'): component = component.component else: break
def __init__(self, connection, **kw): self.scp = SCP02(**kw) self.connection = connection CardConnectionDecorator.__init__(self, connection) if 'GAFdict' in kw: assert isinstance(kw['GAFdict'], dict), "GAF dictionary expected" self.objects = kw['GAFdict'] else: self.objects = {}
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
def transmit(self, bytes, protocol=None): """Cypher/uncypher APDUs before transmission""" cypheredbytes = self.cypher(bytes) data, sw1, sw2 = CardConnectionDecorator.transmit(self, cypheredbytes, protocol) if [] != data: data = self.uncypher(data) return data, sw1, sw2
def getuid(connection: CardConnectionDecorator): data, sw1, sw2 = connection.transmit(cmdMap["getuid"]) uid = toHexString(data).replace(" ", "") if (sw1, sw2) == (0x90, 0x0): return uid else: return None
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
def transmit(self, apdu, protocol=None): """ Wrap APDU and transmit to the card. """ apdu_w = self.scp.wrapAPDU(apdu) resp, sw1, sw2 = CardConnectionDecorator.transmit( self, apdu_w, protocol) if sw1 == 0x61: resp, sw1, sw2 = self.getResponse(sw2) return resp, sw1, sw2
def transmit( self, apdu, protocol=None): """ Wrap APDU and transmit to the card. """ apdu_w = self.scp.wrapAPDU( apdu ) resp, sw1, sw2 = CardConnectionDecorator.transmit( self, apdu_w, protocol ) if sw1 == 0x61: resp, sw1, sw2 = self.getResponse( sw2 ) return resp, sw1, sw2
def transmit(self, bytes, protocol=None): """Cypher/uncypher APDUs before transmission""" cypheredbytes = self.cypher(bytes) data, sw1, sw2 = CardConnectionDecorator.transmit( self, cypheredbytes, protocol) if [] != data: data = self.uncypher(data) return data, sw1, sw2
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 ) ] + \ [ ord( x ) for x in 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 )
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
def getinfo(connection: CardConnectionDecorator) -> dict: atr = ATR(connection.getATR()) hb = toHexString(atr.getHistoricalBytes()) cardname = hb[-17:-12] name = cardnameMap.get(cardname, "Unknown " + str(cardname)) return { "Name": name, "T0": atr.isT0Supported(), "T1": atr.isT1Supported(), "T15": atr.isT15Supported() }
def loadkey(connection: CardConnectionDecorator, key: str): COMMAND = cmdMap.get("loadkey") load_key = [key[0:2], key[2:4], key[4:6], key[6:8], key[8:10], key[10:12]] for i in range(6): load_key[i] = int(load_key[i], 16) COMMAND.extend(load_key) data, sw1, sw2 = connection.transmit(COMMAND) if (sw1, sw2) == (0x90, 0x0): return True elif (sw1, sw2) == (0x63, 0x0): return False
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
def __init__( self, connection, **kw ): self.scp = SCP03( **kw ) self.connection = connection CardConnectionDecorator.__init__( self, connection )
def unmute(connection: CardConnectionDecorator): data, sw1, sw2 = connection.transmit(cmdMap["unmute"]) if (sw1, sw2) == (0x90, 0x0): return True else: return False
def __init__(self, cardconnection): CardConnectionDecorator.__init__(self, cardconnection)
def getATR(self): """Replace first BYTE of ATR by 3F""" atr = CardConnectionDecorator.getATR(self) return [0x3f] + atr[1:]
def firmver(connection: CardConnectionDecorator): data, sw1, sw2 = connection.transmit(cmdMap["firmver"]) version = ''.join(chr(i) for i in data) + chr(sw1) + chr(sw2) return version
def getResponse( self, sw2 ): """ Get Response from the last APDU.""" apdu = [ self.scp.CLA( False, 0 ), 0xC0, 0, 0, sw2 ] return CardConnectionDecorator.transmit( self, apdu )
def __init__(self, connection, **kw): self.objects = kw self.connection = connection CardConnectionDecorator.__init__(self, connection)
def getResponse(self, sw2): """ Get Response from the last APDU.""" apdu = [self.scp.CLA(False, 0), 0xC0, 0, 0, sw2] return CardConnectionDecorator.transmit(self, apdu)
def transmit(self, bytes, protocol=None): '''Gain exclusive access to card during APDU transmission for if this decorator decorates a PCSCCardConnection.''' data, sw1, sw2 = CardConnectionDecorator.transmit( self, bytes, protocol) return data, sw1, sw2
def createConnection(self): """Return a card connection thru PCSC reader.""" return CardConnectionDecorator(PCSCCardConnection(self.name))
def __init__( self, connection, **kw ): self.scp = SCP02( **kw ) self.connection = connection CardConnectionDecorator.__init__( self, connection )