Smart Reader Operation Python engine processNfc script
November 6, 2024 at 4:57 AMPyScore’s processNfc script
*** PRELIMINARY ***
Description
The processNfc
script runs every time the a NFC card is found and activated by the reader. Its role is to implement the transaction with the NFC card. It may also involve a SAM or a Secure Element, should the application require it.
Examples
A simple example, with only a NFC card and no functions
import springcore
import logging
from springcore import *
logging.info("\nRunning PyScore over SpringCore " + springcore.version())
if !springcore.isReader() || (springcore.getReaderEvent() != springcore.READER_EVENT_PROCESS_NFC):
raise Exception("Script invocation error")
# A NFC card just arrived, let's get the corresponding object
card = scard.getNfcReader().getCard()
# NB: no need to call connect; NFC cards are powered up implicitely
# Let's say we want to process a Desfire
# 1st of all, the card must be ISO/IEC 14443 type A
cardType = card.getType()
if cardType != Card.NFC_A:
raise Exception("Card is not NFC-A (therefore not a a Desfire)")
# Send the Desfire GET VERSION instruction (90 60 00 00 00)
resp1, sw1, sw2 = card.transmit([ 0x90, 0x60, 0x00, 0x00, 0x00 ])
if sw1 != 0x90 or sw2 != 0xAF:
raise Exception("Wrong SW, step 1")
# Send the Desfire CONTINUE instruction
resp2, sw1, sw2 = card.transmit([ 0x90, 0xAF, 0x00, 0x00, 0x00 ])
if sw1 != 0x90 or sw2 != 0xAF:
raise Exception("Wrong SW, step 2")
# Send the Desfire CONTINUE instruction
resp3, sw1, sw2 = card.transmit([ 0x90, 0xAF, 0x00, 0x00, 0x00 ])
if sw1 != 0x90 or sw2 != 0xAF:
raise Exception("Wrong SW, step 3")
# Now we have the complete response
desfireVersion = resp1 + resp2 + resp3
# Get the UID, 7 bytes starting at offset 10
desfireUid = desfireVersion[10..17]
logging.info("Desfire UID (hex): " + utils.BytesToHex(desfireUid))
# Translate the UID to a decimal value, and store it into a character string
desfireUid = utils.BytesToDec(desfireUid)
logging.info("Desfire UID (dec): " + str(desfireUid))
# This is the output to be forwarded to the host!
springcore.sendSmartReaderOutput(desfireUid)
A more complex example, using a SAM together with the NFC card and functions
import springcore
import logging
from springcore import *
def processISOA(card, sam):
# Send GET VERSION to the SAM
capdu = [ 0x80, 0x60, 0x00, 0x00, 0x00 ]
data, sw1, sw2 = sam.transmit(capdu)
if sw1 != 0x91 and sw2 != 0x00:
raise Exception("SAM error")
logging.info("SAM version:" + utils.BytesToHex(data))
# Send the Desfire GET VERSION instruction (90 60 00 00 00)
resp1, sw1, sw2 = card.transmit([ 0x90, 0x60, 0x00, 0x00, 0x00 ])
if sw1 != 0x91 or sw2 != 0xAF:
raise Exception("Wrong SW, step 1")
# Send the Desfire CONTINUE instruction
resp2, sw1, sw2 = card.transmit([ 0x90, 0xAF, 0x00, 0x00, 0x00 ])
if sw1 != 0x91 or sw2 != 0xAF:
raise Exception("Wrong SW, step 2")
# Send the Desfire CONTINUE instruction
resp3, sw1, sw2 = card.transmit([ 0x90, 0xAF, 0x00, 0x00, 0x00 ])
if sw1 != 0x91 or sw2 != 0x00:
raise Exception("Wrong SW, step 3")
# Now we have the complete response
desfireVersion = resp1 + resp2 + resp3
# Get the UID, 7 bytes starting at offset 10
desfireUid = desfireVersion[10:17]
logging.info("Desfire UID (hex): " + utils.BytesToHex(desfireUid))
# Translate the UID to a decimal value, and store it into a character string
desfireUid = utils.BytesToDec(desfireUid)
logging.info("Desfire UID (dec): " + str(desfireUid))
# This is the output to be forwarded to the host!
springcore.sendSmartReaderOutput(desfireUid)
logging.info("\nRunning PyScore over SpringCore " + springcore.version())
if !springCore.isEvent(SPRINGCORE_EVENT_PROCESS_NFC):
raise Exception("Script invocation error")
# A NFC card just arrived, let's get the corresponding object
card = scard.getNfcReader().getCard()
# NB: no need to call connect; NFC cards are powered up implicitely
# getSamCard without a parameter returns the card in the first SAM slot
sam = scard.getSamReader().getCard()
# we must make sure that the card is powered
sam.connect()
# Show the ATR, for debugging reasons
logging.info("SAM ATR: " + utils.BytesToHex(sam.getAtr()))
# Let's say we want to process a Desfire
# 1st of all, the card must be ISO/IEC 14443 type A
cardType = card.getType()
if cardType == card.NFC_A:
processISOA(card, sam)
else:
raise Exception("Unexpected card type")
# After processing we want to explicitely send a T=CL DESELECT to reset the NFC card
card.disconnect()
# We want to keep the SAM powered up (to run faster next time), but we reset it anyway
sam.reconnect()