Files
micropython-mfrc522/RfidAccess.py
2021-09-15 16:19:29 -04:00

215 lines
8.0 KiB
Python

class RfidAccess:
NEVER = 0
KEYA = 1
KEYB = 2
KEYAB = 3
ALLBLOCK = -1
def __init__(self):
self.C1 = 0
self.C2 = 0
self.C3 = 8
self.C1_Inv = 15
self.C2_Inv = 15
self.C3_Inv = 7
self.Valid=False
def findAccessIndex(self,table,mask,accessbits):
for i in range(8):
if table[i] == accessbits:
if (i & 1) == 0 :
self.C2 = self.C2 & ~mask
else:
self.C2 = self.C2 | mask
if (i & 2) == 0 :
self.C1 = self.C1 & ~mask
else:
self.C1 = self.C1 | mask
if (i & 4) == 0:
self.C3 = self.C3 & ~mask
else:
self.C3 = self.C3 | mask
self.C1_Inv = self.C1 ^ 0xf
self.C2_Inv = self.C2 ^ 0xf
self.C3_Inv = self.C3 ^ 0xf
return True
return False
def setTrailerAccess(self,keyA_Write=KEYA, access_Read=KEYA,access_Write=KEYA,keyB_Read=KEYA,keyB_Write=KEYA):
#C1 weight 2 , C2 weight 1 , C3 weight 4
# Key A Wr Access R Access W KeyB R KEYB W
access_Index = ( (self.KEYA, self.KEYA, self.NEVER, self.KEYA,self.KEYA),
(self.NEVER,self.KEYA,self.NEVER,self.KEYA,self.NEVER),
(self.KEYB, self.KEYAB,self.NEVER,self.NEVER,self.NEVER),
(self.NEVER,self.KEYAB,self.NEVER,self.NEVER,self.NEVER),
(self.KEYA,self.KEYA,self.KEYA,self.KEYA,self.KEYA),
(self.KEYB,self.KEYAB,self.KEYB,self.NEVER,self.KEYB),
(self.NEVER,self.KEYAB,self.KEYB,self.NEVER,self.NEVER),
(self.NEVER,self.KEYAB,self.NEVER,self.NEVER,self.NEVER))
if self.findAccessIndex(access_Index,8, (keyA_Write,access_Read,access_Write,keyB_Read,keyB_Write)):
return True
else:
print("Access Trailer method not possible")
return False
def setBlockAccess(self, blockID, access_Read=KEYAB, access_Write=KEYAB, access_Inc=KEYAB, access_Dec=KEYAB):
# C1 weight 2 , C2 weight 1 , C3 weight 4
# Key Read Key Write INCREment decrement/transfer/etc
access_Blk_idx=((self.KEYAB, self.KEYAB, self.KEYAB, self.KEYAB,None),
(self.KEYAB, self.NEVER, self.NEVER, self.NEVER,None),
(self.KEYAB, self.KEYB, self.NEVER, self.NEVER,None),
(self.KEYAB, self.KEYB, self.KEYB, self.KEYAB,None),
(self.KEYAB, self.NEVER, self.NEVER, self.KEYAB,None),
(self.KEYB, self.KEYB, self.NEVER, self.NEVER,None),
(self.KEYB, self.NEVER, self.NEVER, self.NEVER,None),
(self.NEVER, self.NEVER, self.NEVER, self.NEVER,None))
if(blockID == self.ALLBLOCK):
Mask = 7
elif (BlockID<0) or (blockID >3):
return false
else:
Mask = 1 << blockID
if self.findAccessIndex(access_Blk_idx,Mask,( access_Read, access_Write, access_Inc, access_Dec, None)):
return True
else:
print("**** Error Access Block method not possible")
return False
def encodeAccess(self):
self.C1 = self.C1 & 0xf
self.C2 = self.C2 & 0xf
self.C3 = self.C3 & 0xf
self.C1_INV = self.C1 ^ 0xf
self.C2_INV = self.C2 ^ 0xf
self.C3_INV = self.C3 ^ 0xf
byte6 = self.C2_INV << 4 | self.C1_INV
byte7 = self.C1 << 4 | self.C3_INV
byte8 = self.C3 << 4 | self.C2
return (byte6, byte7, byte8)
def decodeAccess(self, byte6,byte7,byte8):
self.C1_Inv = byte6 & 0xf
self.C2_Inv = (byte6 & 0xf0) >> 4
self.C3_Inv = byte7 & 0xf
self.C1 = (byte7 & 0xf0) >> 4
self.C2 = byte8 & 0xf
self.C3 = (byte8 & 0xf0) >>4
return ((self.C1 ^ self.C1_Inv) & (self.C2 ^ self.C2_Inv) & (self.C3 ^ self.C3_Inv)) & 0xf == 0xf
def decodeAccessFromBlock3(self, block3):
if len(block3)!= 16:
return False
return self.decodeAccess(block3[6],block3[7],block3[8])
def showTrailerAccess(self):
KeyAWrite = ['key A', 'never', 'key B', 'never', 'key A', 'key B', 'never', 'never']
AccessRead = ['key A', 'key A', 'key A|B', 'key A|B', 'key A','key A|B','key A|B','key A|B' ]
AccessWrite = ['never', 'never', 'never', 'never', 'key A', 'key B', 'key B', 'never']
KeyBRead = ['key A data R/W', 'key A data R', 'never', 'never', 'key A data R/W', 'never', 'never', 'never']
KeyBWrite = ['key A data R/W', 'never', 'key B', 'never', 'key A data R/W', 'key B', 'never', 'never']
index = 0
if self.C2 & 0x8 > 0:
index = 1
if self.C1 & 0x8 > 0:
index = index + 2
if self.C3 & 0x8 > 0:
index = index + 4
#print("TrailerAccess idx=",index)
print('Access key A read => never')
print('Access key A write =>', KeyAWrite[index])
print('Access key B read =>', KeyBRead[index])
print('Access key B write =>', KeyBWrite[index])
print('Access bits read =>', AccessRead[index])
print('Access bits write =>', AccessWrite[index])
def showBlockAccess(self,blockID):
BlockRead = ['key A|B','key A|B','key A|B','key A|B','key A|B','key B', 'key B', 'never' ]
BlockWrite = ['key A|B', 'never', 'key B', 'key B', 'never', 'key B','never', 'never']
BlockIncrement = ['key A|B', 'never', 'never', 'key B', 'never', 'never', 'never', 'never']
BlockDecrement = ['key A|B', 'never', 'never', 'key A|B', 'key A|B', 'never', 'never', 'never']
if blockID == 3:
self.showTrailerAccess()
else:
mask = 1 << blockID
index = 0
if (self.C2 & mask) > 0:
index =1
if (self.C1 & mask) > 0:
index = index + 2
if (self.C3 & mask) > 0:
index = index + 4
print("Block ", blockID, " read =>", BlockRead[index])
print("Block ", blockID, " write =>", BlockWrite[index])
print("Block ", blockID, " Increment =>", BlockIncrement[index])
print("Block ", blockID, " Decrement+ =>", BlockDecrement[index])
def showAccess(self):
print("/--------- SHOW ACCESS ---------\\")
AccessB = self.encodeAccess()
print('Access Bytes (6,7,8)= (',hex(AccessB[0]),', ',hex(AccessB[1]),', ',hex(AccessB[2]),')')
print('(C1, C2, C3) = (',hex(self.C1),', ',hex(self.C2),', ',hex(self.C3),')')
for i in range(4):
self.showBlockAccess(i)
print("\\---------------------------------/")
def fillBlock3(self,keyA=None,keyB=None,block=None):
if block is None:
block = 16*[0xff]
if len(block) != 16:
block = 16*[0xff]
if keyA is not None:
if len(keyA) == 6 :
block[0:6]=keyA
if keyB is not None:
if len(keyB) == 6 :
block[10:16]=keyB
b6, b7, b8 = self.encodeAccess()
block[6]=b6
block[7]=b7
block[8]=b8
return block
if __name__ == "__main__":
rfid = RfidAccess()
print("\nEx: Decode access_bits for [0xff, 0x07, 0x80]")
if rfid.decodeAccess(0xFF,0x07,0x80):
rfid.showAccess()
else:
print('Invalid Access')
print("\n\nSet block 0 to 3 to be read by KEYA but R/W with KEYB")
rfid.setBlockAccess(rfid.ALLBLOCK, access_Read=rfid.KEYAB, access_Write=rfid.KEYB, access_Inc=rfid.NEVER, access_Dec=rfid.NEVER)
print("Set sector trailer to be only set by Key B");
rfid.setTrailerAccess(keyA_Write=rfid.KEYB,access_Read=rfid.KEYAB,access_Write=rfid.KEYB,keyB_Read=rfid.NEVER,keyB_Write=rfid.KEYB)
rfid.showAccess()