NFC_Badge/enroll.py

148 lines
3.6 KiB
Python
Raw Normal View History

2023-07-11 20:16:30 +00:00
import nfc
from nfc.clf import RemoteTarget
import logging
from time import time
import os.path
import coloredlogs
coloredlogs.install()
from base64 import b16encode, b16decode
import sys
import ndef
import binascii
from badge import Badge
from os import system
CONFIG_PAGES = {
"NXP NTAG213": (0x29, 0x2A, 0x2B, 0x2C),
"NXP NTAG215": (0x83, 0x84, 0x85, 0x86),
"NXP NTAG216": (0xE3, 0xE4, 0xE5, 0xE6),
}
session_start = time()
if __name__ == '__main__':
log = logging.getLogger('nfc')
nfc_type = sys.argv[1]
balance = 0
if len(sys.argv) > 2:
balance = sys.argv[2]
elif nfc_type == 'coin':
log.error("You cannot create empty coins.")
exit()
clf = nfc.ContactlessFrontend()
log.info(f"Enrolling mode: {nfc_type}")
log.info(f"Initial balance: {balance}")
try:
assert clf.open('tty:USB0:pn532')
except TimeoutError:
log.error('Got TimeoutError on reader connection attempt.')
except AssertionError:
log.error('There is no reader connected.')
exit()
# Set baud rate to 115200 to prevent reader from dying
clf.device.chipset.set_serial_baudrate(115200)
clf.device.chipset.transport.baudrate = 115200
try:
while 1:
target = clf.sense(RemoteTarget('106A'), iterations=10)
if not target: continue
start = time()
tag = nfc.tag.activate(clf, target)
if not tag:
print("Tag was gone while writing.")
break
if tag.product not in ["NXP NTAG215"]:
raise Exception(f"This tag ({tag.product}) is not compatible with the barcard system.")
#print("\n".join(tag.dump()))
#break
badge = Badge(tag)
password = badge.password()
try:
has_password = tag.read(CONFIG_PAGES[tag.product][0])[3] < 0xFF
except:
break
if has_password:
log.warning("TAG has a password already! Trying to re-enroll anyway.")
tag.authenticate(password)
#tx = Transaction(tag_id=tag.identifier)
try:
# Disable the mirror, for now
page_addr = CONFIG_PAGES[tag.product][0]
page = tag.read(page_addr)[:4]
page[0] &= 0b111111 # Disable UID + COUNT mirror
tag.write(page_addr, page)
except:
break
# Activate it again
tag = nfc.tag.activate(clf, target)
if has_password:
tag.authenticate(password)
# Write the correct url depending on the type of wanted badge
if nfc_type == 'badge':
url = "https://go.foxo.me/fz23/bxxxxxxxxxxxxxxxxxxxxx"
else:
url = f"https://go.foxo.me/fz23/cxxxxxxxxxxxxxxxxxxxxx"
tag.format()
tag.ndef.records = [ndef.uri.UriRecord(url), ]
if tag.ndef.records[0].uri != url:
raise Exception("Written uri is different than expected.")
boundary = tag.read(0x08)
if not boundary.startswith(b"e/fz23/"):
raise Exception(f"This tag does not seem to correctly store ndef data. Got wrong {boundary}")
try:
page_addr = CONFIG_PAGES[tag.product][0]
page = tag.read(page_addr)[:4]
page[0] |= 0b11 << 6 # Enable UID + COUNT mirror
if tag.product == 'NXP NTAG215':
page[2] = 0x0A # Location of UID + COUNT
elif tag.product == 'NXP NTAG213':
page[2] = 0x0B
tag.write(page_addr, page)
log.info("UID + COUNT mirror enabled.")
except:
raise
break
print('EC')
badge.enable_count()
tag = nfc.tag.activate(clf, target)
if not has_password:
print('PRT')
badge.protect()
with open(f'log_{int(session_start)}.txt', 'a') as f:
f.write(f"{b16encode(tag.identifier).decode()},{nfc_type},{balance}\n")
system('mpv success.wav')
log.info(f"{time()-start:.2f} tag write done.")
while clf.sense(RemoteTarget('106A')): pass
system
except KeyboardInterrupt:
pass
clf.close()