I am trying to modify an existing SCardTransmit() command (C#) that currently reads one security status/block from a ISO 15693 vicinity RFID card (TI Tag-it HF), to one that will retrieve the security status for all 64 blocks on the card. The existing code is as follows:
Byte[] sendHeader = { 0xFF, 0x30, 0x00, 0x03, 0x05, 0x01, 0x00, 0x00, 0x00, Convert.ToByte(blockNum), 0x01 };
Byte[] sendBuffer = new Byte[255]; //Send Buffer in SCardTransmit
int sendbufferlen; //Send Buffer length in SCardTransmit
SmartCardData pack = new SmartCardData();
sendHeader.CopyTo(sendBuffer, 0);
sendbufferlen = Convert.ToByte(sendHeader.Length);
SCardTransmitReceived rxBuf = SmartCardTransmit(sendBuffer, sendbufferlen);
The way I understand it, the bytes preceding Convert.ToByte(blockNum) represent the command to get a security status, followed by the block in question, and the number of blocks to read. The only reference I have seen regarding security status reads is in section 10.3.4 in the "Contactless Smart Card Reader Dev Guide"
NOTE: SmartCardTransmit takes care of calling SCardTransmit with the correct card handle and the other needed parameters. I'm more interested in the format of the send header that represents a request for security blocks 0 to 63.
Unfortunately, that is not possible. The Get Security Status command of the HID/Omnikey smartcard reader can only retrieve the security status of one block with each command. So regardless of what Le byte you try to provide, the reader will always only return the security status of the block you specify with blockNum.
So the only way to get the security status for all blocks is by iterating through all blocks and issuing the command for each of them:
bool moreBlocks = true;
int blockNum = 0;
while (moreBlocks) {
byte[] sendBuffer = {
0xFF, 0x30, 0x00, 0x03,
0x05,
0x01,
0x00, 0x00,
(byte)((blockNum>>8) & 0xFF), (byte)(blockNum & 0xFF),
0x00
};
SCardTransmitReceived rxBuf = SmartCardTransmit(sendBuffer, sendBuffer.Length);
moreBlocks = check_if_rxBuf_ends_with_sw9000(rxBuf);
++blockNum;
}
From this document:
link
it appears that your tag complies with ISO15693 standard. From the documentation you have provided it appears that the command you need is at page 59. Now, from the description of the command it appears 0x01 is Version and the following two bytes (0x00 and 0x00) means reading by block. The byte before Convert.ToByte() seams to be the MSB of the starting block (0x00). The Convert.ToByte() is the LSB of the starting block. The next is Le in command description (the number of blocks to be read).
Related
I'm starting to learn java card and I'm reading a sample code of a wallet and there an OwnerPin in it.
Here's the part of the code, related to the pin and its verification:
OwnerPIN pin;
private myApplet(byte[] bArray, short bOffset, byte bLength) {
// It is good programming practice to allocate
// all the memory that an applet needs during
// its lifetime inside the constructor
pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
byte iLen = bArray[bOffset]; // aid length
bOffset = (short) (bOffset + iLen + 1);
byte cLen = bArray[bOffset]; // info length
bOffset = (short) (bOffset + cLen + 1);
byte aLen = bArray[bOffset]; // applet data length
// The installation parameters contain the PIN
// initialization value
pin.update(bArray, (short) (bOffset + 1), aLen);
register();
}
I'm having a little trouble understanding this code. I know that this is the part when the pin is set according to the installation script:
0x80 0xB8 0x00 0x00 0xd 0xb 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x00 0x00 0x00 0x7F;
I can't understand what is the value of pin will be after installing the applet.
The shown code is not enough to actually say anything about the given APDU.
This code sample though:
byte iLen = bArray[bOffset]; // aid length
bOffset = (short) (bOffset + iLen + 1);
byte cLen = bArray[bOffset]; // info length
bOffset = (short) (bOffset + cLen + 1);
byte aLen = bArray[bOffset]; // applet data length
is the default code for the Applet's installation method, therefore could be triggered by a Global Platform INSTALL command. However, the given APDU is not a valid Global Platform at all.
From your code we cannot see the entrypoint of the APDU in the process method, but probably it works like this: the given data is a LV-encoded list (Length/Value), therefore you parse the length byte for aid first, save the length iLen and increment bOffset to the next LV-pair. in the end the value and length of the applet data is taken and feeded into the pin.update.
In the given APDU, the PIN is acutally missing, try to parse the contents and length for aid and info and you will see that the applet data bytes are missing.
I'm working on an extension to Node Media Server to save incoming streams to disk as MP4. For this conversion to MP4 I'm leaning heavily on the Apple QuickTime Movie Specification, The ISO/IEC 14496-14 Specification (which I discovered in the Rust-MP4 GitHub repository for free), and The HLS.js Source Code
I'm testing with a single video at the moment. Once this works I'll start experimenting with other videos. For my use case I only need to support H.264 video and AAC audio.
Currently when an RTMP connection is established, the first 3 packets I receive are consistently:
1 AMF metadata packet (RTMP cid = 6) containing information like video width, video height, bitrate, audio sample rate, etc
1 audio packet (RMTP cid = 4) containing 7 bytes of data. I assume this is the AAC config packet
1 video packet (RTMP cid = 5) containing 46 bytes of data. I assume this is the AVC config packet
When writing the MP4 moov atom, there are two places where I need to utilize additional information not located in the AMF metadata (and presumably located in these two config packets):
In the esds atom, The HLS.js source appends "config" data. I assume I just append the entire 7-byte payload from the audio config packet here
In the avcC atom, The HLS.js source append the "sps" and "pps" data. This is the root of my issue
Regarding the parsing of these 46 bytes, I found code in Node Media Server and HLS.js that seems to parse the same data. The difference between these two pieces of code is that Node Media Server expects an additional 13 bytes of data at the start of the packet. The packet I receive seems to contain these additional 13 bytes, so I simply follow their lead in extracting width, height, profile, compat, and level information. The 46 bytes in particular are:
[0x17, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0xc0, 0x1f, 0xff, 0xe1, 0x00, 0x19, 0x67, 0x42, 0xc0, 0x1f, 0xa6, 0x11, 0x02, 0x80, 0xbf, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc2, 0x3c, 0x60, 0xc8, 0x46, 0x01, 0x00, 0x05, 0x68, 0xc8, 0x42, 0x32, 0xc8]
Breaking this down for the bytes I can easily parse (prior to the use of Exponential Golomb encoding):
[
0x17, // "frame type", specifies H.264 or HVEC
0x00, 0x00, 0x00, 0x00, 0x01, // ignored. Reserved?
0x42, // profile
0xc0, // compat
0x1f, // level
0xff, // "info.nalu" (per Node Media Server source)
0xe1, // "info.nb_sps" (per Node Media Server source)
0x00, 0x19, // "nal size"
// Above here are the bits exclusively seen by Node Media Server (specific to RTMP?)
// Below here are the bits passed to HLS.js as "unit.data" (common to all AVC1 streams?):
0x67, // "nal type"
0x42, // profile (again?)
0xc0, // compat (again?)
0x1f, // level (again?)
// Below here, data is not necessarily byte-aligned as Exponential Golomb encoding is used
// ...
]
Now the problem I'm running into is during the creation of the moov atom (and the avcC atom, specifically) I need to know both the sps and the pps bytes. From the HLS.js source it looks like the sps may just be this video config packet minus the first 13 bytes. However how do I find the pps? Is pps actually the last few bytes of this packet, and I should split it somewhere? Will this be delivered in another packet? If two video packets are to be expected, is there some way I should differentiate them so I know which one is sps and which one is pps?
If I can figure out this last little bit, then I should be completely done writing the moov packet (after which point I just need to figure out the proper format for the mdat packet and I should have working code)
Update: For the record, I just checked the fourth packet being delivered to see if it might contain pps data. After reconnecting to the stream ~20 times the fourth packet was consistently a video packet (RTMP cid = 5), but the size of the packet ranged from 16000 bytes to 21000 bytes. I suspect this is legitimate video data.
Second Update: I just checked what the offset was in the video config packet when I finished parsing the SPS, and I was on byte 23 (0x84). It's therefore likely that the PPS is in fact at the end of this byte array, but I'm not sure how many bytes are delimiters / headers (NAL type, NAL length, etc) and how many bytes are the actual PPS.
I'm trying to retrieve my sensor data from my Raspberry Pi using nrf24l01+ network receiver.
I'm sending it from an Arduino nano board. Here is the setting of my Arduino:
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xcccccc3ccc 0xcccccc3c3c
RX_ADDR_P2-5 = 0x33 0xce 0x3e 0xe3
TX_ADDR = 0xcccccccc3c
RX_PW_P0-6 = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA = 0x3e
EN_RXADDR = 0x3f
RF_CH = 0x5a
RF_SETUP = 0x07
CONFIG = 0x0f
DYNPD/FEATURE = 0x3f 0x04
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX
My Raspberry Pi is plugged with nrf24l01+ through GPIO. I made sure the connection is OK by using the C++ example given on https://github.com/TMRh20/RF24:
RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ);
The data is OK. Now i want to use a nodeJS program to get this data. I'm using this library: https://github.com/natevw/node-nrf
The code is very simple, but somehow is not working (console is silent):
var spiDev = "/dev/spidev0.0";
var cePin = 15; //RPI_BPLUS_GPIO_J8_15
var irqPin = null;
var channel = 0x5a; //90
var radio = require('nrf').connect(spiDev, cePin, irqPin);
radio
.channel(channel)
.dataRate('1Mbps')
.crcBytes(1)
// .autoRetransmit({count:15, delay:4000})
;
radio.begin(function () {
var rx = radio.openPipe('rx', 0xcccccccc3c);
rx.pipe(process.stdout);
});
I'm wondering what I'm doing wrong. Hardware is OK and the setting seems pretty good, what do you think?
Thanks
Usually to find out what is wrong with NRF you should start from basics:
Try simpler NRF configs to test if its working, especially with no CRC bytes etc.
Try it w/o dynamic payload and try fixed payload size on both ends.
Auto-acknowledge also can be an issue (note that when auto-ack is enabled, CRC can't be disabled as it is used to ensure transmission acknowledgement in this mode).
Ensure that CRC lengths match on both ends. In your example on Arduino you have CRC Length = 16 bits whether Raspberry configured with radio.crcBytes(1).
Don't rely on default values, always provide same full configuration on both ends.
These steps can considerably reduce time to locate the problem especially when using different libraries and platforms.
I have a BYTE data[3]. The first element, data[0] has to be a BYTE with very specific values which are as follows:
typedef enum
{
SET_ACCURACY=0x01,
SET_RETRACT_LIMIT=0x02,
SET_EXTEND_LIMT=0x03,
SET_MOVEMENT_THRESHOLD=0x04,
SET_STALL_TIME= 0x05,
SET_PWM_THRESHOLD= 0x06,
SET_DERIVATIVE_THRESHOLD= 0x07,
SET_DERIVATIVE_MAXIMUM = 0x08,
SET_DERIVATIVE_MINIMUM= 0x09,
SET_PWM_MAXIMUM= 0x0A,
SET_PWM_MINIMUM = 0x0B,
SET_PROPORTIONAL_GAIN = 0x0C,
SET_DERIVATIVE_GAIN= 0x0D,
SET_AVERAGE_RC = 0x0E,
SET_AVERAGE_ADC = 0x0F,
GET_FEEDBACK=0x10,
SET_POSITION=0x20,
SET_SPEED= 0x21,
DISABLE_MANUAL = 0x30,
RESET= 0xFF,
}TYPE_CMD;
As is, if I set data[0]=SET_ACCURACY it doesn't set it to 0x01, it sets it to 1, which is not what I want. data[0] must take the value 0x01 when set it equal to SET_ACCURACY. How do I make it so that it does this for not only SET_ACCURACY, but all the other values as well?
EDIT: Actually this works... I had a different error in my code that I attributed to this. Sorry!
Thanks!
"data[0]=SET_ACCURACY doesn't set it to 0x01, it sets it to 1"
It assigns value of SET_ACCURACY to the data[0], which means that bits 00000001 are stored into memory at address &data[0]. 0x01 is hexadecimal representation of this byte, 1 is its decimal representation.
Am working on a project to read from and write data to smart cards. The Card Reader am using is ACR38U-H1 from ACS. Following their APDU commands, I have being able to get access to the card and read some data. But am suspecting that I still have not being able to read the exact data inside, because always I get a response to the command APDU 0x6e 0x00, 0x00 instead of0x90 0x00.
What am I doing wrong?
Maybe the problem is in the smart card?
Python code:
#! /usr/bin/env python
from smartcard.scard import *
import smartcard.util
SELECT = [
#0xA0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00
0XFF, 0xA4, 0x00, 0x00, 0x01, 0x05
]
COMMAND = [
0x00, 0xC0, 0x00, 0x00, 0x00, 0x0B
]
try:
hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to establish context : ' +
SCardGetErrorMessage(hresult))
print 'Context established!'
try:
hresult, readers = SCardListReaders(hcontext, [])
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to list readers: ' +
SCardGetErrorMessage(hresult))
print 'PCSC Readers:', readers
if len(readers) < 1:
raise Exception('No smart card readers')
reader = readers[0]
print "Using reader:", reader
try:
hresult, hcard, dwActiveProtocol = SCardConnect(hcontext, reader,
SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1 | SCARD_PROTOCOL_T1)
if hresult != SCARD_S_SUCCESS:
raise Exception('Unable to connect: ' +
SCardGetErrorMessage(hresult))
print 'Connected with active protocol', dwActiveProtocol
try:
hresult, response = SCardTransmit(hcard, dwActiveProtocol,
SELECT)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to transmit: ' +
SCardGetErrorMessage(hresult))
print 'Select: ' + smartcard.util.toHexString(response,
smartcard.util.HEX)
#==========================================================================
hresult, response = SCardTransmit(hcard, dwActiveProtocol,
COMMAND)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to transmit: ' +
SCardGetErrorMessage(hresult))
print 'Command: ' + smartcard.util.toHexString(response,
smartcard.util.HEX)
# =========================================================================
finally:
hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to disconnect: ' +
SCardGetErrorMessage(hresult))
print 'Disconnected'
except Exception, message:
print "Exception:", message
finally:
hresult = SCardReleaseContext(hcontext)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to release context: ' +
SCardGetErrorMessage(hresult))
print 'Released context.'
except Exception, message:
print "Exception:", message
Result of this code:
Context established!
PCSC Readers: ['ACS ACR38U-CCID 00 00']
Using reader: ACS ACR38U-CCID 00 00
Connected with active protocol 2
Select: 0x6E 0x00
Command: 0x67 0x00
Disconnected
Released context.
Result of open-tool:
[17:06:00]:~$ opensc-tool -s ff:a4:00:00:01:05
Using reader with a card: ACS ACR38U-CCID 00 00
Sending: FF A4 00 00 01 05
Received (SW1=0x6E, SW2=0x00)
You are using SELECT_CARD_TYPE APDU command (0xFF00000101) which is meant to be used with I2C memory cards (up to 16 kilobits specifically) -- see section 9.3.1.1 in the reader reference manual.
This SELECT_CARD_TYPE command (having CLA set to 0xFF) is not addressed to the card but to the reader (which refuses it as the card does not use I2C).
Your card is a microprocessor card speaking T=1 protocol so you need to use "normal" ISO 7816 APDUs -- which ones should be specified in your card documentation.
Nevertheless there is a script for Smart Card Shell 3 tool which seems to read (and in a limited way emulate) FOMS card (I have not tried).
Given the script source it seems that card supports standard ISO 7816-4 SELECT and READ_BINARY APDU commands which are used behind new CardFile() and CardFile.readBinary().
Good luck!
Disclaimer: I have worked neither with any FOMS card nor with the scsh3 tool.
SELECT = [
#0xA0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00
0XFF, 0xA4, 0x00, 0x00, 0x01, 0x05
]
Here it seems you are trying to select MF ( AID = 3F00 on commented # command) OR Command seems wrong because no AID is of 1 byte length , Please check your command
0XFF, 0xA4, 0x00, 0x00, 0x01, 0x05 // check it.
and getting 6E 00 Class not supported
Your other command is C0 - GET RESPONSE,
COMMAND = [
0x00, 0xC0, 0x00, 0x00, 0x00, 0x0B
]
This command is used to get the response from the card of length specified by previous command having return code like - 61 XX and APDU sequence should like
CLASS, INS, P1, P2, Le //please check your Get Response command
Here Get Response giving 6700 , it seems correct because previous command is failed already and card does not have nothing to return to it so unable to return Le data ( 0x0B - Suppose it is your Le)
I suggest , understand your card well before firing any command, seems it is a proprietary card so you should know the file structure/CLASS byte USED before sending command, when you shoot with correct CLA value, hope you will not get - CLA not supported error.
Hope this information helps to identify the problem.