Changing key in Mifare 4K Card - rfid

Can anyone please tell me how to change a key in a Mifare 4K classic card.
What I tried was
<newKeyA> + access bits + <KeyB>
0xAA 0xAA 0xAA 0xAA 0xAA 0xAA 0X78 0x77 0x88 0x69 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
But the key refuses to change. The default configuration is 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF.

In order to change the access keys of a sector on a MIFARE Classic card, you simply have to update that sector's trailer block.
So, for instance, if your current key B is FFFFFFFFFFFF (and the current access conditions permit writing of the sector trailer with key B), you would first authenticate for that sector with that current key B.
Then, you would create your new sector trailer:
<new key A> | access bits | general purpose byte | <new key B>
For instance:
AAAAAAAAAAAA 787788 69 BBBBBBBBBBBB
to have key A set to AAAAAAAAAAAA and key B set to BBBBBBBBBBBB with these access conditions:
Trailer block: C1=0,C2=1,C3=1 &rightarrow; Sector trailer is writable using key B only; access bits/GPB can be read with key A or B.
Data blocks: C1=1, C2=0, C3=0 &rightarrow; Write is possible using key B only; read is permitted with key A or B.
Finally, you can write the new sector trailer to the trailer block, which is the last block (i.e. block 3) of each sector.

Related

How to calculate C-MAC from EXTERNAL AUTHENTICATE command apdu?

Thanks to these informations I'm able to calculate EXTERNAL_AUTHENTICATE_data but how exactly can I calculate MAC ?
I know that my default C-MAC key is [40 41 ... 4F]. I have tried to encrypt [84 82 00 00 10]+EXTERNAL_AUTHENTIFICATE apdu with it using 3DES in CBC mode but it doesn't give the MAC value I expect.
With the help of this tutorial, these are the steps I followed to "Calculate C-MAC" :
1 - I take the apdu with EXTERNAL_AUTHENTICATE_data : 8482000010448126B770B27702
2 - I pad this apdu : 8482000010448126B770B27702800000
3 - I encrypt the data with the first 8 bytes of S-MAC key : single DES in CBC mode (key : D1C28C601652A477 / IV : 00 00 00 00 00 00 00 00) result => 25F7DC3B1FEE1B9018CCD8E66A69B560
4 - I encrypt this with the last 8 bytes of S-MAC key : 3DES in EBC mode (key : 0D67AD82D2D2E1C4) result => 11E1B058F0EB6910196A68BF1FBA97AA
Or the result I except is D770D0A0001B05AA
Did I do the retail MAC wrong ?
I've developed a Python class for the SCP02. The MAC-related secions may answer your question:
from Crypto.Cipher import DES3,DES
ZERO_IV_8 = b"\x00\x00\x00\x00\x00\x00\x00\x00"
last_mac = None
def pad_80(data_list):
reminder = len(data_list) % 8
if reminder != 0:
return data_list + [0x80,] + [0x00 for i in range(8 - reminder - 1)]
else:
return data_list + [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
def calc_mac(command):
padded_command = self.pad_80(command)
mac_in = bytes.fromhex(toHexString(padded_command).replace(" ", ""))
iv = ZERO_IV_8
if last_mac != None:
cipher = DES.new(session_mac[:8], DES3.MODE_ECB)
iv = cipher.encrypt(last_mac)
cipher = DES.new(session_mac[:8], DES3.MODE_CBC, iv)
step1 = cipher.encrypt(mac_in)
cipher = DES.new(session_mac[8:16], DES3.MODE_ECB)
step2 = cipher.decrypt(step1[-8:])
cipher = DES.new(session_mac[:8], DES3.MODE_ECB)
mac = list(bytes(cipher.encrypt(step2[-8:])))
last_mac = bytes.fromhex(toHexString(mac).replace(" ", ""))
return mac
The variable session_mac is a 16-bytes byte strings which contains session MAC key. You also need to keep the calculated MAC in a variable (in my case last_mac) to use it as IV for next command MAC calculation.
The calc_mac function input (command) is a list of numbers as the APDU Command. You need to fix CLA and LC values before MAC calculation.
I see two mistakes:
the last block needs to be encrypted three times instead of 4 (single DES + 3DES is one first round too many);
you are not using both keys for your 3DES, in which case it probably reverts to single DES encryption.
As for the last point, it performs DES encrypt with single key given, decrypt with single key given and a final encrypt again. So two of these operations are cancelling each other out. This is deliberate in the design of triple 3DES to make a single HW implementation be able to do both.
I think this is mentioned in the earlier question, but beware, MAC generally uses bit padding: a byte with 0x80 always padded, with as many 0x00 bytes to reach the next block boundary.
Note that Bouncy Castle contains Retail MAC.

USB HID Codes mystery

I'm currently writing out USB HID codes in Python 3....
NULL_CHAR = chr(0)
def write_report(report):
with open('/dev/hidg0', 'rb+') as fd:
fd.write(report.encode())
# Press SHIFT + a = A
write_report(chr(32)+NULL_CHAR+chr(4)+NULL_CHAR*5)
# Release all keys
write_report(NULL_CHAR*8)
My question:
By looking at the standard "USB HID Usage Tables" from USB.org ( v1.12 - 10-21-2004 - https://www.usb.org/document-library/hid-usage-tables-112 ) ...
I know from actively running the example above
( Using "USAGE ID" in Decimal FYI ), that CHR(32) is a < SHIFT >, but in the HID table it shows that a Decimal (32) is a Keyboard < 3 > or < # > ..
What's up with that ?
Am I using the wrong table, Should i be using ASCii codes instead of USB HID Keyboard codes ?
Is there a better/more accurate table of codes ?
Because if chr(32) is in reality a < SHIFT >, what then would be < 3 > ?
Is there an easier way to type Function Keys ( F1+F3+F5 ) in combination, in addition to full text lines, and issue them out over USB than the way i'm currently doing it ?
Any help to clear this up by the pro's here would be greatly appreciated !!!
Not sure if you still need the answer, but I figured out after a day of headache over the same thing.
The information you're sending always must be transferred as 8 bytes.
So from your example:
write_report(chr(32)+NULL_CHAR+chr(4)+NULL_CHAR*5)
The chr(32) is Byte 0 (which is the modifier), then comes a null char at Byte 1, then the actual char at Byte 2, then another 5 nullchars, to make it 8.
Modifiers follow a different system from actual chars.
LCTRL 0x01
LSHIFT 0x02
LALT 0x04
LMETA 0x08
RCTRL 0x10
RSHIFT 0x20
RALT 0x40
RMETA 0x80
So the reason for 32 is because that's the decimal equivalent of 0x20 in hex.
Hope this helps you, or anyone else looking for this answer.

ISO 15693: read multiple security blocks

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).

Confused about "three successive writes: bytes 10, bytes 32, bytes 54"?

I am learning SMSC smc91cx driver code, and I learned how to program test code for smc91c111 nic by the instructions of Application Note 9-6. I cannot understand the following instructions under "Transmitting A Packet":
Write the destination address (three successive writes: bytes 10, bytes 32, bytes 54)
Write 0xFFFF, 0xFFFF, 0xFFFF
Write the source address (three successive writes: bytes 10, bytes32, bytes 54)
Write 0x0000, 0x0000, 0x0000
I cannot make sense of these instructions. Should I write 10 bytes size of 0xFF plus 32 bytes size plus 54 bytes size to the buffer, or just write 0xFF in 10th byte postion, 32th, 54th byte postion?
But if so, why would you write 0x0000 to the same position?
Rather than allocating several different registers to write to, that chip has you write to the same DATA register serially until you set all the info. The DATA register is 2 bytes wide, but a MAC address is 6 bytes, numbered 0-5. So you have to write it 2 bytes at a time: bytes number 1 and 0 first, followed by bytes number 3 and 2, then bytes number 5 and 4. Then write 0xFFFF 3 times to the DATA register, then repeat for the source address and the 0x0000s.

How to correctly calculate address spaces?

Below is an example of a question given on my last test in a Computer Engineering course. Anyone mind explaining to me how to get the start/end addresses of each? I have listed the correct answers at the bottom...
The MSP430F2410 device has an address space of 64 KB (the basic MSP430 architecture). Fill in the table below if we know the following. The first 16 bytes of the address space (starting at the address 0x0000) is reserved for special function registers (IE1, IE2, IFG1, IFG2, etc.), the next 240 bytes is reserved for 8-bit peripheral devices, and the next 256 bytes is reserved for 16-bit peripheral devices. The RAM memory capacity is 2 Kbytes and it starts at the address 0x1100. At the top of the address space is 56KB of flash memory reserved for code and interrupt vector table.
What Start Address End Address
Special Function Registers (16 bytes) 0x0000 0x000F
8-bit peripheral devices (240 bytes) 0x0010 0x00FF
16-bit peripheral devices (256 bytes) 0x0100 0x01FF
RAM memory (2 Kbytes) 0x1100 0x18FF
Flash Memory (56 Kbytes) 0x2000 0xFFFF
For starters, don't get thrown off by what's stored in each segment - that's only going to confuse you. The problem is just asking you to figure out the hex numbering, and that's not too difficult. Here are the requirements:
64 KB total memory
The first 16 bytes of the address space (starting at the address 0x0000) is reserved for special function registers (IE1, IE2, IFG1, IFG2, etc.)
The next 240 bytes is reserved for 8-bit peripheral devices
The next 256 bytes is reserved for 16-bit peripheral devices
The RAM memory capacity is 2 Kbytes and it starts at the address 0x1100
At the top of the address space is 56KB of flash memory reserved for code and interrupt vector table.
Since each hex digit in your memory address can handle 16 values (0-F), you'll need 4 digits to display 64KB of memory (16 ^ 4 = 65536, or 64K).
You start with 16 bytes, and that covers 0x0000 - 0x000F (one full digit of your address). That means that the next segment, which starts immediately after it (8-bit devices), begins at 0x0010 (the next byte), and since it's 240 bytes long, it ends at byte 256 (240 + 16), or 0x00FF.
The next segment (16-bit devices) starts at the next byte, which is 0x0100, and is 256 bytes long - that puts the end at 0x01FF.
Then comes 2KB (2048 bytes) of RAM, but it starts at 0x1100, as the description states, instead of immediately after the previous segment, so that's your starting address. Add 2048 to that, and you get 0x18FF.
The last segment covers the upper section of the memory, so you'll have to work backwards, You know it ends at 0xFFFF (the end of the available memory), and it's 56KB long. If you convert the 56KB to hex, it's 0xDFFF. If you imagine that this segment starts at 0, That leaves 2000 unused (0xE000-0xEFFF and 0xF000-0xFFFF), so you know that this segment has to start at 0x2000 to end at the upper end of the memory space.
I hope that's more clear, though when I read over it, I don't know that it's any help at all :( Maybe that's why I'll leave teaching that concept to somebody more qualified...
#define NUM_SIZES 5
uint16_t sizes[5] = {16, 240, 256, 2 * 1024, 56 * 1024};
uint16_t address = 0;
printf("Start End\n");
for (int i = 0; i < NUM_SIZES; i++)
{
printf("0x%04X 0x%04X\n", address, address + sizes[i] - 1);
address += sizes[i];
}

Resources