mirror of
https://github.com/brmlab/brmdoor_libnfc.git
synced 2025-06-08 00:24:00 +02:00
Sending APDUs
This commit is contained in:
parent
703c214421
commit
6ae565373a
3 changed files with 127 additions and 1 deletions
|
@ -9,9 +9,23 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
ResponseAPDU::ResponseAPDU(const string &data)
|
||||||
|
{
|
||||||
|
size_t len = data.size();
|
||||||
|
_valid = len >= 2;
|
||||||
|
|
||||||
|
if (!_valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sw = (uint8_t(data[len-2]) << 8) | uint8_t(data[len-1]);
|
||||||
|
_data = data.substr(0, len-2);
|
||||||
|
}
|
||||||
|
|
||||||
NFCDevice::NFCDevice() throw(NFCError):
|
NFCDevice::NFCDevice() throw(NFCError):
|
||||||
pollNr(20),
|
pollNr(20),
|
||||||
pollPeriod(2),
|
pollPeriod(2),
|
||||||
|
apduTimeout(500),
|
||||||
_nfcContext(NULL),
|
_nfcContext(NULL),
|
||||||
_nfcDevice(NULL),
|
_nfcDevice(NULL),
|
||||||
_opened(false),
|
_opened(false),
|
||||||
|
@ -105,6 +119,36 @@ std::string NFCDevice::scanUID() throw(NFCError)
|
||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NFCDevice::selectPassiveTarget() throw(NFCError)
|
||||||
|
{
|
||||||
|
nfc_target nt;
|
||||||
|
while (nfc_initiator_select_passive_target(_nfcDevice, _modulations[0], NULL, 0, &nt) <= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResponseAPDU NFCDevice::sendAPDU(const string &apdu) throw(NFCError)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
uint8_t rapdu[512];
|
||||||
|
|
||||||
|
if ((res = nfc_initiator_transceive_bytes(_nfcDevice, (uint8_t*)apdu.data(), apdu.size(),
|
||||||
|
rapdu, 512, apduTimeout)) < 0) {
|
||||||
|
if (res == NFC_EOVFLOW) {
|
||||||
|
throw NFCError("Response APDU too long");
|
||||||
|
}
|
||||||
|
|
||||||
|
throw NFCError("Failed to transceive APDU");
|
||||||
|
} else {
|
||||||
|
string rapduData((char *)rapdu, res);
|
||||||
|
ResponseAPDU responseApdu(rapduData);
|
||||||
|
|
||||||
|
if (!responseApdu.valid()) {
|
||||||
|
throw NFCError("Invalid response APDU was received");
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseApdu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const nfc_modulation NFCDevice::_modulations[5] = {
|
const nfc_modulation NFCDevice::_modulations[5] = {
|
||||||
{ /*.nmt = */ NMT_ISO14443A, /* .nbr = */ NBR_106 }
|
{ /*.nmt = */ NMT_ISO14443A, /* .nbr = */ NBR_106 }
|
||||||
//{ /*.nmt = */ NMT_ISO14443B, /* .nbr = */ NBR_106 },
|
//{ /*.nmt = */ NMT_ISO14443B, /* .nbr = */ NBR_106 },
|
||||||
|
|
|
@ -29,6 +29,45 @@ protected:
|
||||||
std::string _msg;
|
std::string _msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents response APDU for ISO14443-4.
|
||||||
|
*/
|
||||||
|
class ResponseAPDU
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Parse response APDU from raw data */
|
||||||
|
ResponseAPDU(const std::string& data);
|
||||||
|
|
||||||
|
~ResponseAPDU() {}
|
||||||
|
|
||||||
|
/** Return whole status word */
|
||||||
|
uint16_t sw() const {return _sw;}
|
||||||
|
|
||||||
|
/** Return first byte of status word */
|
||||||
|
uint8_t sw1() const {return _sw >> 8;}
|
||||||
|
|
||||||
|
/** Return second byte of status word */
|
||||||
|
uint8_t sw2() const {return _sw & 0xFF;}
|
||||||
|
|
||||||
|
/** Return whether this is properly formed response */
|
||||||
|
bool valid() const {return _valid;}
|
||||||
|
|
||||||
|
/** Returns APDU data */
|
||||||
|
const std::string& data() const {return _data;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Data from response, without SW1 and SW2 */
|
||||||
|
std::string _data;
|
||||||
|
|
||||||
|
/** SW1 and SW2 */
|
||||||
|
uint16_t _sw;
|
||||||
|
|
||||||
|
/** Whether response APDU has had enough data to be valid */
|
||||||
|
bool _valid;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents one PN532 reader device. Config is taken from default
|
* Represents one PN532 reader device. Config is taken from default
|
||||||
* libnfc-specified location. That usually means first device found is used.
|
* libnfc-specified location. That usually means first device found is used.
|
||||||
|
@ -68,6 +107,20 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string scanUID() throw(NFCError);
|
std::string scanUID() throw(NFCError);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for one passive or emulated target and select it by reader.
|
||||||
|
*/
|
||||||
|
void selectPassiveTarget() throw(NFCError);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send APDU to passive or emulated target. The target must be already
|
||||||
|
* selected by selectPassiveTarget() or scanUID().
|
||||||
|
*
|
||||||
|
* @param apdu command APDU to send
|
||||||
|
* @param returns response APDU received from target
|
||||||
|
*/
|
||||||
|
ResponseAPDU sendAPDU(const std::string& apdu) throw(NFCError);
|
||||||
|
|
||||||
/** Open device explicitly. May be useful after explicit close */
|
/** Open device explicitly. May be useful after explicit close */
|
||||||
void open() throw(NFCError);
|
void open() throw(NFCError);
|
||||||
|
|
||||||
|
@ -95,6 +148,11 @@ public:
|
||||||
*/
|
*/
|
||||||
uint8_t pollPeriod;
|
uint8_t pollPeriod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timeout for waiting response to sent APDU. Value -1 means wait forever.
|
||||||
|
*/
|
||||||
|
int apduTimeout;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** Modulations that specify cards accepted by reader */
|
/** Modulations that specify cards accepted by reader */
|
||||||
|
|
26
test_nfc.py
26
test_nfc.py
|
@ -2,9 +2,33 @@
|
||||||
from brmdoor_nfc import NFCDevice, NFCError
|
from brmdoor_nfc import NFCDevice, NFCError
|
||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
|
|
||||||
|
def formatAPDU(apdu):
|
||||||
|
return " ".join(["%02X" % ord(b) for b in apdu])
|
||||||
|
|
||||||
|
# Reading of file E104, where usually NDEF message is
|
||||||
|
hex_apdus = [
|
||||||
|
"00 A4 04 00 07 D2760000850101",
|
||||||
|
"00 a4 00 0c 02 E104",
|
||||||
|
"00 b0 00 00 30",
|
||||||
|
]
|
||||||
|
|
||||||
|
apdus = [hex_apdu.replace(" ","").decode("hex") for hex_apdu in hex_apdus]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
nfc = NFCDevice()
|
nfc = NFCDevice()
|
||||||
print hexlify(nfc.scanUID())
|
uid = nfc.scanUID()
|
||||||
|
print "UID", hexlify(uid)
|
||||||
|
|
||||||
|
print "Now trying to send ISO14443-4 APDUs"
|
||||||
|
try:
|
||||||
|
#nfc.selectPassiveTarget()
|
||||||
|
for apdu in apdus:
|
||||||
|
print "Command APDU:", formatAPDU(apdu)
|
||||||
|
rapdu = nfc.sendAPDU(apdu)
|
||||||
|
print "Response APDU valid: %s, SW %04x, data %s" % (rapdu.valid(), rapdu.sw(), hexlify(rapdu.data()))
|
||||||
|
except NFCError, e:
|
||||||
|
print "Failed to transmit APDU:", e.what()
|
||||||
|
|
||||||
print "Device is opened:", nfc.opened()
|
print "Device is opened:", nfc.opened()
|
||||||
print "Closing device"
|
print "Closing device"
|
||||||
nfc.close()
|
nfc.close()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue