PyScore’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()