Recover sector in Mifare Classic 1k with overwritten permission bits - nfc

I have mistakenly overwritten sector 1 block 7 of one of my Mifare classic 1k tags. It was meant for testing and the 16 byte data that I wrote on block 7 is shown below:
0xaa 0xaa 0xaa 0xaa
0xbb 0xbb 0xbb 0xbb
0xcc 0xcc 0xcc 0xcc
0xdd 0xdd 0xdd 0xdd
If not mistaken, by doing so, my access keys and permission bits have become as following:
Key-A: 0xaa 0xaa 0xaa 0xaa 0xbb 0xbb
Key-B: 0xcc 0xcc 0xdd 0xdd 0xdd 0xdd
Permisssion Bits: --> 0xbb 0xbb 0xcc
I have tried to use Key-A and Key-B as shown above to read/write block 7 in sector 1. But I am no longer able to access (no read or write) any block in sector 1 anymore.
I know the keys to all other sectors (e.g. sector 0 and sectors 2-15) and able to access them.
Considering the situation, I would like to know if there is any way to reset sector 1 or block 7 to regain my access. Many thanks.
Update:
I have confirmed that both Key-A and Key-B as shown above are correct and I can authenticate to the card with both of them. Also, as per the Mifare Classic specification (screenshot), my access bits are as follows:
Byte 6 = 0xbb = 0b10111011
--------------------------
C2_3 C2_2 C2_1 C2_0 C1_3 C1_2 C1_1 C1_0
1 1 0 1 1 1 0 1
Byte 7 = 0xbb = 0b10111011
--------------------------
C1_3 C1_2 C1_1 C1_0 C3_3 C3_2 C3_1 C3_0
1 1 0 1 1 1 0 1
Now, considering the specification/screenshot, C1_3, C2_3 and C3_3 bits enable read/write access to sector-trailer. In my case, for block 7 (trailer for sector 7) they are all set to 1. Should I not have write access to this block then?

Once the Access Control bits are not configured correctly (for example, bits that are supposed to be each other's complement are not complementary, like in your case), the sector cannot be accessed anymore at all.

In the Mifare classic specification you linked says:
Remark: With each memory access the internal logic verifies the format
of the access conditions. If it detects a format violation the whole
sector is irreversibly blocked.
Your access bytes does not verify the format. In the folowing table ~ means inverted
Byte 6
--------------------------
~C2_3 ~C2_2 ~C2_1 ~C2_0 ~C1_3 ~C1_2 ~C1_1 ~C1_0
1 0 1 1 1 0 1 1
Byte 7
--------------------------
C1_3 C1_2 C1_1 C1_0 ~C3_3 ~C3_2 ~C3_1 ~C3_0
1 0 1 1 1 0 1 1
Byte 8
--------------------------
C3_3 C3_2 C3_1 C3_0 C2_3 C2_2 C2_1 C2_0
1 1 0 0 1 1 0 0
So, for instance, C2_3 = 1 and ~C2_3 = 1. They are not complementary. Format not verified, sector is irreversibily blocked.
In the same document there is a table (table 7) that shows that keyA can always be readed. Maybe this is the reason you can authenticate.

Related

trying to understand how checksum is calculated

I am looking at this page and I am not sure how the author is calculating the checksum. I would contact the author directly, but don't have his email address (its not listed in github).
This is a simple example of a packet with no variables. The author calculates the checksum to be 120 (I assume this is hex as all his other values are in hex). The sum of all the bytes is 0xBA hex or 186 base(10). His notes say "Checksum Low Bit, This bit is checksum of 1-5 bits (MOD 256, if necessary)" but I am not getting what he is saying and I can't figure out how to get to his answer.
Get Version / Return Name
Byte 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Request 16 2 80 20 2 120 16 3
Byte Sample hex Definition
hex (B10)
==== ==== ===== =============================
1 0x16 (22) Preamble 1
2 0x02 (2) Preamble 2
3 0x80 (128) Destination = Chlorinator
4 0x20 (32) Command = Get Name
5 0x02 (2) Not sure. Intellitouch uses 2. Aquarite uses 0. Any of them seem to work.
6 120 Checksum Low Bit, This bit is checksum of 1-5 bits (MOD 256, if necessary)
7 0x16 (22) Post-amble 1
8 0x3 (3) Post-amble 2
Any suggestions would be most appreciated!
Turns out that the commentors were 100% correct: the numbers were express in decimal, not hex as I assumed.

Checking if an adress is linecache aligned

This is a quiz question which I failed in the past and despite having access to the solution, I don't understand the different step to come to the correct answer.
Here is the problem :
Which of these adress is line cache aligned
a. 0x7ffc32a21164
b. 0x560c40e05350
c. 0x560c40e052c0
d. 0x560c3f2d71ff
And the solution to the problem:
Each hex char is represented by 4 bits
It takes 6 bits to represent 64 adress, since ln(64)/ln(2) = 6
0x0 0000
0x4 0100
0x8 1000
0xc 1100
________
2^3 2^2 2^1 2^0
8 4 2 1
Conclusion: if the adress ends if either 00, 40, 80 or c0, then it is aligned on 64 bytes.
The answer is c.
I really don't see how we go from 6 bits representation to this answer. Can anyone adds something to the solution given to make it clearer?
The question boils down to: Which number is a multiple of 64? All that remains is understanding the number system they're using.
In binary, 64 is written as 1000000. In hexadecimal, it's written as 0x40. So multiples of 64 will end in 0x00 (0 * 64), 0x40 (1 * 64), 0x80 (2 * 64), or 0xC0 (3 * 64). (The cycle then repeats.) Answer c is the one with the right ending.
An analogy in decimal would be: Which number is a multiple of 5? 0 * 5 is 0 and 1 * 5 is 5, after which the cycle repeats. So we just need to look at the last digit. If it's a 0 or a 5, we know the number is a multiple of 5.

Direct mapped cache example

i am really confused on the topic Direct Mapped Cache i've been looking around for an example with a good explanation and it's making me more confused then ever.
For example: I have
2048 byte memory
64 byte big cache
8 byte cache lines
with direct mapped cache how do i determine the 'LINE' 'TAG' and "Byte offset'?
i believe that the total number of addressing bits is 11 bits because 2048 = 2^11
2048/64 = 2^5 = 32 blocks (0 to 31) (5bits needed) (tag)
64/8 = 8 = 2^3 = 3 bits for the index
8 byte cache lines = 2^3 which means i need 3 bits for the byte offset
so the addres would be like this: 5 for the tag, 3 for the index and 3 for the byte offset
Do i have this figured out correctly?
Do i figured out correctly? YES
Explanation
1) Main memmory size is 2048 bytes = 211. So you need 11 bits to address a byte (If your word size is 1 byte) [word = smallest individual unit that will be accessed with the address]
2) You can calculating tag bits in direct mapping by doing (main memmory size / cash size). But i will explain a little more about tag bits.
Here the size of a cashe line( which is always same as size of a main memmory block) is 8 bytes. which is 23 bytes. So you need 3 bits to represent a byte within a cashe line. Now you have 8 bits (11 - 3) are remaining in the address.
Now the total number of lines present in the cache is (cashe size / line size) = 26 / 23 = 23
So, you have 3 bits to represent the line in which the your required byte is present.
The number of remaining bits now are 5 (8 - 3).
These 5 bits can be used to represent a tag. :)
3) 3 bit for index. If you were trying to label the number of bits needed to represent a line as index. Yes you are right.
4) 3 bits will be used to access a byte withing a cache line. (8 = 23)
So,
11 bits total address length = 5 tag bits + 3 bits to represent a line + 3 bits to represent a byte(word) withing a line
Hope there is no confusion now.

FAT filesystem: calculate the size and search a byte

I have this question in an Operating System test:
Given a disk of 1GB with 16KB blocks:
(1) Calculate the size of the File Allocation Table:
My Answer: since there are 2^16 blocks in the disk, we have a table with 2^16 entry, and every entry needs to store 16 bit (since there are 2^16 different blocks, we need 16 bit to identify each of them). So the size is 2^16 times 16 bit = 2^16 x 2^4 = 2^20 bit = 2^17 byte = 128Kb.
(2) Given the following table, indicate in which block are stored the following byte:
-byte 131080 of FileA starting at block 4.
-byte 62230 of FileB starting at block 3.
Entry Content
0 10
1 2
2 0
3 6
4 1
5 8
6 7
7 11
8 12
So FileA is (4) -> (1) -> (2) but the problem is: since every block is 16Kb = 2^4 x 2^10 byte = 2^14 byte = 16384 byte, block 4 contains from 1 to 16384, block 1 contains from 16385 to 32768, and block 2 from 32769 to 49152, where am I supposed to find the byte 131080???
Where is this wrong??

What is the best way of sending the data to serial port?

This is related with microcontrollers but thought to post it here because it is a problem with algorithms and data types and not with any hardware stuff. I'll explain the problem so that someone that doesn't have any hardware knowledge can still participate :)
In Microcontroller there is an Analog to Digital converter with 10
bit resolution. (It will output a
value between 0 and 1023)
I need to send this value to PC using the serial port.
But you can only write 8 bits at once. (You need to write bytes). It is
a limitation in micro controller.
So in the above case at least I need to send 2 bytes.
My PC application just reads a sequence of numbers for plotting. So
it should capture two consecutive
bytes and build the number back. But
here we will need a delimiter
character as well. but still the delimiter character has an ascii value between 0 - 255 then it will mixup the process.
So what is a simplest way to do this? Should I send the values as a sequence of chars?
Ex : 1023 = "1""0""2""3" Vs "Char(255)Char(4)"
In summary I need to send a sequence of 10 bit numbers over Serial in fastest way. :)
You need to send 10 bits, and because you send a byte at a time, you have to send 16 bits. The big question is how much is speed a priority, and how synchronised are the sender and receiver? I can think of 3 answers, depending on these conditions.
Regular sampling, unknown join point
If the device is running all the time, you aren't sure when you are going to connect (you could join at any time in the sequence) but sampling rate is slower than communication speed so you don't care about size I think I'd probably do it as following. Suppose you are trying to send the ten bits abcdefghij (each letter one bit).
I'd send pq0abcde then pq1fghij, where p and q are error checking bits. This way:
no delimiter is needed (you can tell which byte you are reading by the 0 or 1)
you can definitely spot any 1 bit error, so you know about bad data
I'm struggling to find a good two bit error correcting code, so I guess I'd just make p a parity bit for bits 2,3 and 4 (0, a b above) and q a parity bit for 5 6 and 7 (c,d,e above). This might be clearer with an example.
Suppose I want to send 714 = 1011001010.
Split in 2 10110 , 01010
Add bits to indicate first and second byte 010110, 101010
calculate parity for each half: p0=par(010)=1, q0=par(110)=0, p1=par(101)=0, q1=par(010)=1
bytes are then 10010110, 01101010
You then can detect a lot of different error conditions, quickly check which byte you are being sent if you lose synchronisation, and none of the operations take very long in a microcontroller (I'd do the parity with an 8 entry lookup table).
Dense data, known join point
If you know that the reader starts at the same time as the writer, just send the 4 ten bit values as 5 bytes. If you always read 5 bytes at a time then no problems. If you want even more space saving, and have good sample data already, I'd compress using a huffman coding.
Dense data, unknown join point
In 7 bytes you can send 5 ten bit values with 6 spare bits. Send 5 values like this:
byte 0: 0 (7 bits)
byte 1: 1 (7 bits)
byte 2: 1 (7 bits)
byte 3: 1 (7 bits)
byte 4: 0 (7 bits)
byte 5: 0 (7 bits)
byte 6: (8 bits)
Then whenever you see 3 1's in a row for the most significant bit, you know you have bytes 1, 2 and 3. This idea wastes 1 bit in 56, so could be made even more efficient, but you'd have to send more data at a time. Eg (5 consecutive ones, 120 bits sent in 16 bytes):
byte 0: 0 (7 bits) 7
byte 1: 1 (7 bits) 14
byte 2: 1 (7 bits) 21
byte 3: 1 (7 bits) 28
byte 4: 1 (7 bits) 35
byte 5: 1 (7 bits) 42
byte 6: 0 (7 bits) 49
byte 7: (8 bits) 57
byte 8: (8 bits) 65
byte 9: (8 bits) 73
byte 10: (8 bits) 81
byte 11: 0 (7 bits) 88
byte 12: (8 bits) 96
byte 13: (8 bits) 104
byte 14: (8 bits) 112
byte 15: (8 bits) 120
This is quite a fun problem!
The best method is to convert the data to an ASCII string and send it that way - it makes debugging a lot easier and it avoids various communication issues (special meaning of certain control characters etc).
If you really need to use all the available bandwidth though then you can pack 4 10 bit values into 5 consecutive 8 bit bytes. You will need to be careful about synchronization.
Since you specified "the fastest way" I think expanding the numbers to ASCII is ruled out.
In my opinion a good compromise of code simplicity and performance can be obtained by the following encoding:
Two 10bit values will be encoded in 3 bytes like this.
first 10bit value bits := abcdefghij
second 10bit value bits := klmnopqrst
Bytes to encode:
1abcdefg
0hijklmn
0_opqrst
There is one bit more (_) available that could be used for a parity over all 20bits for error checking or just set to a fixed value.
Some example code (puts 0 at the position _):
#include <assert.h>
#include <inttypes.h>
void
write_byte(uint8_t byte); /* writes byte to serial */
void
encode(uint16_t a, uint16_t b)
{
write_byte(((a >> 3) & 0x7f) | 0x80);
write_byte(((a & 3) << 4) | ((b >> 6) & 0x7f));
write_byte(b & 0x3f);
}
uint8_t
read_byte(void); /* read a byte from serial */
void
decode(uint16_t *a, uint16_t *b)
{
uint16_t x;
while (((x = read_byte()) & 0x80) == 0) {} /* sync */
*a = x << 3;
x = read_byte();
assert ((x & 0x80) == 0); /* put better error handling here */
*a |= (x >> 4) & 3;
*b = x << 6;
x = read_byte();
assert ((x & 0xc0) == 0); /* put better error handling here */
*b |= x;
}
I normally use a start byte and checksum and in this case fixed length, so send 4 bytes, the receiver can look for the start byte and if the next three add up to a know quantity then it is a good packet take out the middle two bytes, if not keep looking. The receiver can always re-sync and it doesnt waste the bandwidth of ascii. Ascii is your other option, a start byte that is not a number and perhaps four numbers for decimal. Decimal is definitely not fun in a microcontroller, so start with something non-hex like X for example and then three bytes with the hex ascii values for your number. Search for the x examine the next three bytes, hope for the best.

Resources