ISO 7816-4 How to construct this C-APDU to write? - nfc

I'm interfacing with a smart card (ISO 7816-4)
I have been given the below C-APDU to read a value:
CLA = 0x90
INS = 0x4C
p1 = 0x00
p2 = 0x00
length = 4
parameters = empty
Which returns the response 00000 2f4 9000
(9000 being what I understand to be the SW1/SW2, and the 2f4 part of that response contains the relevant data that I want to change)
Given this provided info, is it possible to determine what modifications to this C-APDU would I need to make to instead UPDATE this data (2f4) to be a different value?
I am quite new to this, and am trying to learn, so thank you for your responses.

My understanding is that CLA of 90 means a proprietary command set and an instruction (INS) 4C does not match any of the industry instruction commands.
Thus as this looks like a proprietary read command it is most likely that the update command is proprietary to the hardware you are issuing it to, so impossible to guess what it should be.

Related

How do I interpret a python byte string coming from F1 2020 game UDP packet?

Title may be wildly incorrect for what I'm trying to work out.
I'm trying to interpret packets I am recieving from a racing game in a way that I understand, but I honestly don't really know what I'm looking at, or what to search to understand it.
Information on the packets I am recieving here:
https://forums.codemasters.com/topic/54423-f1%C2%AE-2020-udp-specification/?tab=comments#comment-532560
I'm using python to print the packets, here's a snippet of the output, which I don't understand how to interpret.
received message: b'\xe4\x07\x01\x03\x01\x07O\x90.\xea\xc2!7\x16\xa5\xbb\x02C\xda\n\x00\x00\x00\xff\x01\x00\x03:\x00\x00\x00 A\x00\x00\xdcB\xb5+\xc1#\xc82\xcc\x10\t\x00\xd9\x00\x00\x00\x00\x00\x12\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$tJ\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01
I'm very new to coding, and not sure what my next step is, so a nudge in the right direction will help loads, thanks.
This is the python code:
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 20777
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(4096)
print ("received message:", data)
The website you link to is describing the data format. All data represented as a series of 1's and 0's. A byte is a series of 8 1's and 0's. However, just because you have a series of bytes doesn't mean you know how to interpret them. Do they represent a character? An integer? Can that integer be negative? All of that is defined by whoever crafted the data in the first place.
The type descriptions you see at the top are telling you how to actually interpret that series of 1's and 0's. When you see "unit8", that is an "unsigned integer that is 8 bits (1 byte) long". In other words, a positive number between 0 and 255. An "int8" on the other hand is an "8-bit integer", or a number that can be positive or negative (so the range is -128 to 127). The same basic idea applies to the *16 and *64 variants, just with 16 bits or 64 bits. A float represent a floating point number (a number with a fractional part, such as 1.2345), generally 4 bytes long. Additionally, you need to know the order to interpret the bytes within a word (left-to-right or right-to-left). This is referred to as the endianness, and every computer architecture has a native endianness (big-endian or little-endian).
Given all of that, you can interpret the PacketHeader. The easiest way is probably to use the struct package in Python. Details can be found here:
https://docs.python.org/3/library/struct.html
As a proof of concept, the following will interpret the first 24 bytes:
import struct
data = b'\xe4\x07\x01\x03\x01\x07O\x90.\xea\xc2!7\x16\xa5\xbb\x02C\xda\n\x00\x00\x00\xff\x01\x00\x03:\x00\x00\x00 A\x00\x00\xdcB\xb5+\xc1#\xc82\xcc\x10\t\x00\xd9\x00\x00\x00\x00\x00\x12\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$tJ\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'
#Note that I am only taking the first 24 bytes. You must pass data that is
#the appropriate length to the unpack function. We don't know what everything
#else is until after we parse out the header
header = struct.unpack('<HBBBBQfIBB', data[:24])
print(header)
You basically want to read the first 24 bytes to get the header of the message. From there, you need to use the m_packetId field to determine what the rest of the message is. As an example, this particular packet has a packetId of 7, which is a "Car Status" packet. So you would look at the packing format for the struct CarStatus further down on that page to figure out how to interpret the rest of the message. Rinse and repeat as data arrives.
Update: In the format string, the < tells you to interpret the bytes as little-endian with no alignment (based on the fact that the documentation says it is little-endian and packed). I would recommend reading through the entire section on Format Characters in the documentation above to fully understand what all is happening regarding alignment, but in a nutshell it will try to align those bytes with their representation in memory, which may not match exactly the format you specify. In this case, HBBBBQ takes up 2 bytes more than you'd expect. This is because your computer will try to pack structs in memory so that they are word-aligned. Your computer architecture determines the word alignment (on a 64-bit computer, words are 64-bits, or 8 bytes, long). A Q takes a full word, so the packer will try to align everything before the Q to a word. However, HBBBB only requires 6 bytes; so, Python will, by default, pad an extra 2 bytes to make sure everything lines up. Using < at the front both ensures that the bytes will be interpreted in the correct order, and that it won't try to align the bytes.
Just for information if someone else is looking for this. In python there is the library f1-2019-telemetry existing. On the documentation, there is a missing part about the "how to use" so here is a snippet:
from f1_2020_telemetry.packets import *
...
udp_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
udp_socket.bind((host, port))
while True:
udp_packet = udp_socket.recv(2048)
packet = unpack_udp_packet(udp_packet)
if isinstance(packet, PacketSessionData_V1): # refer to doc for classes / attribute
print(packet.trackTemperature) # for example
if isinstance(packet, PacketParticipantsData_V1):
for i, participant in enumerate(packet.participants):
print(DriverIDs[participant.driverId]) # the library has some mapping for pilot name / track name / ...
Regards,
Nicolas

NXP NTAG 424: write command returns 917E: "Length Error"". Why?

I have started working with the NXP NTAG 424 TT chip together with nfcpy and an Identive SCL3711 Reader/Writer. I can successfully send and receive APDU commands, securely authenticate myself and send and receive commands in encrypted communication mode.
However I can't read or write Data to the chip, and I don't know why. Here is what I do (mostly taken from the NXP application note Page 24):
I send the command "ISO Select NDEF application using DF Name"
00A404C07D276000085010100
Then I perform the secure authentication protocol via AuthenticatEV2First with key 0x00
I try to write some data as follows:
cmd_header = 02000000040000
cmd_data = 00D1FF00 (before padding)
cmd_data = 00D1FF00800000000000000000000000 (after padding)
The complete command which I send looks like this:
cla cmd P1&2| Lc |ISO Header | encrypted Data |LE
90 8D 00 00 1F 02 000000 040000 6688A4D75482FC972C2447A1A20F0AC9C073C1CF506B2BD3 00
However the chip only responds with 917E: "Length Error"" which translates to "Command size not allowed"
What am I doing wrong? It can't be the encryption, I tested that with various other commands (getTTStatus, SetConfiguration) and these all worked fine. I quadruple checked the header. Did I perhaps fail to select the correct File, or did I miss some other steps? Also what does "Command size not allowed" mean? This error is pretty cryptic to me (which is funny when working with encrypted chips :D).
Any help is greatly appreciated!
Best regards,
Phil
The length of "encrypted data" field in your case is 24 bytes, whereas the length which you have mentioned in ISO Header is "040000" i.e. 4 bytes.
Your encrypted data length should match with the length of data you are writing.
In your case there is mismatch in both lengths and resulting in error.
Hope the information is clear.
Cheers!

ASCII control of VFD

All,
I am a new user here, and thought I would see if the experts could help me with something I am new to.
I have been given the following statement to try and solve:
The Variable Frequency Drive (VFD) is connected to the PLC by RS485 communication. The speed of the motor (M2) can be adjusted by sending the following command:
STX N DATA ETX , with each separate value having the <> symbols around them.
Data : Length of data is 1 byte, in which the value of S (Slow), M (Medium) or F (Fast) can be sent.
N : Node number of the VFD, with a data length of two byte ASCII.
My question is, how would I type to send this data? It doesn't say whether to use a specific data type to represent, so surely I could just type the data as it is, e.g. STX 1 S ETX?
Othwerside, I'm not sure how to combine the byte representations of the data, representing them in hex, binary or decimal. I'm not sure what is meant by two byte ASCII, is this not UNICODE-16? Also, I'm not sure if I need to send the values of STX or ETX with the data string or not
I hope someone can shed some light on this.
Thanks in advance.
Since the frequency goes from 0-50 Hz, I think we should send data in this range.
So if we want the frequency to be half maximal, we will send 25.
To send this to VFD, we first need to split that number into 2 and 5
The message should read STX 2 5 ETX?
Now we look at the ASCII code table and find 2 and 5.
0x50 = 2
0x53 = 5
We convey everything in a message that reads
STX 0x50 0x53 ETX
The aforementioned S7-300 is recommended for operation. You can also solve this through his TIA portal.
All,
I managed to figure this out with a bit of digging. I simulated it using Siemens S7-300 on TIA portal, and set up communications on a module. I sent the values I wanted using a "move" block, to a value set in the Data Block.
I repeated this for the Node value, making sure the correct data type was chosen, and sent the data through a Send_ptp command block.
Must have got a bit flustered and tired the other night when I was trying it. Hopefully it might help someone in the future.

Error in reading and writing data on Mifare DESFire cards

I am trying to read and write data on Mifare DESFire cards using ISO 7816-4 APDU commands. I followed the steps:
Select application using {00,A4,04,00,07,D2,76,00,00,85,01,00}.
I get the response as 9100.
Then I select file using {00,A4,00,00,02,3F,00} and I get the response as 9100.
Then I try to read the file using command {00,B0,00,00,03} and I get an error with code 6A86.
Now I want to know the exact commands to read and write the data on the cards. I think I still don't get the meaning of P1 and P2 in read/write commands. I already tried many other combinations but I always get errors like 6A86, 6982, etc.
I assume you receive the status word 9000 on success. If you actually receive 9100 when using ISO/IEC 7816-4 basic inter-industry command APDUs something very strange must be going on. 91xx status words should only be returned when you use the ISO/IEC 7816-4 wrapped command set (i.e. when the class byte of the command APDU is set to 0x90).
Let's look at what you currently do:
You start my selecting the MIFARE DESFire ISO AID D2760000850100:
00 A4 0400 07 D2760000850100
This makes sure that the card is in ISO/IEC 7816-4 framing mode and automatically selects the MF (master file; i.e. the PICC level application).
You then, again(!), select the MF (PICC level application):
00 A4 0000 02 3F00
So you are now at the same level as after step 4.
Finally, you try to read 3 bytes starting at offset 0 from the currently selected file using the READ BINARY APDU:
00 B0 0000 03
Since the currently selected file is the MF you can't read binary data from it. The MF does not have a data part. Consequently, the card reports the error code 6A86 ("wrong parameter P1 and/or P2") as it tries to tell you that reading at offset 0 (P1|P2 = 0x0000) from the MF (currently selected file indicated by the upper bit of P1 being zero) makes no sense.
Therefore, before you can read binary data, you need to select an elementary file (EF), probably even located in a different application (dedicated file, DF), that contains an actual data part. This can be done bei either explicitly sending SELECT commands for EF (and, if necessary, the DF) or by implicitly selecting the EF using a short file identifier in P1 of the first read binary command. In the latter case, you would set the upper bit of P1 to one to indicate that the remaining part of P1 encodes a short file ID. In both cases you would need to know the file/application identifiers of the files and applications that you want to read from.

Read java card uid [duplicate]

i am looking for APDU to find UID of contact less ISO 14443 smart card and how to use it to print in Linux terminal. Problem is that i found many people talking about it, but there is no solution. Can anyone help is this regard???
Thanks
"Get Data Command" is defined in PCSC 3 v2. If your driver is PCSC v2 compliant, you can get UID using it:
Class = 0xFF
INS = 0xCA
P1 = 0x00
P2 = 0x00
Le = 0x00 (return full length: ISO14443A single 4 bytes, double 7 bytes, triple 10 bytes, for ISO14443B 4 bytes PUPI, for 15693 8 bytes UID)
Returned value is:
Data+SW1SW2
See the other answer, it is likely that most readers do support the pass through to the card reader by now.
Nobody can help as the UID is specified in the ISO 14443 T=CL transport protocol while APDU's are specified in the ISO 7816 application layer protocol.
So you need access to a lower level API for your contactless reader. PCSC will not suffice (unless there has been a pass through implemented for the specific reader that returns the UID).

Resources