258 lines
6.2 KiB
C

#include "mfrc522data.h"
#include <includes.h>
#include "rfid-spi.h"
#include "time.h"
mifaredata_t mifare_card_data;
#define START_BLOCK 44
#define NR_KNOWN_KEYS 2
uint8_t knownKeys[NR_KNOWN_KEYS][MF_KEY_SIZE] = {
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // FF FF FF FF FF FF = factory default
{0xa5, 0xaa, 0xa5, 0xa5, 0xaa, 0xaa}, // A5 AA A5 A5 AA AA
};
mifaredata_t* get_mifare_data()
{
return &mifare_card_data;
}
void set_mifare_data(mifaredata_t* data)
{
memcpy(&mifare_card_data, &data, sizeof(mifaredata_t));
}
/**
* Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tuples C1 is MSB (=4) and C3 is LSB (=1).
*/
void MIFARE_SetAccessBits( uint8_t *accessBitBuffer, ///< Pointer to byte 6, 7 and 8 in the sector trailer. Bytes [0..2] will be set.
uint8_t g0, ///< Access bits [C1 C2 C3] for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)
uint8_t g1, ///< Access bits C1 C2 C3] for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)
uint8_t g2, ///< Access bits C1 C2 C3] for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)
uint8_t g3 ///< Access bits C1 C2 C3] for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39)
) {
uint8_t c1 = ((g3 & 4) << 1) | ((g2 & 4) << 0) | ((g1 & 4) >> 1) | ((g0 & 4) >> 2);
uint8_t c2 = ((g3 & 2) << 2) | ((g2 & 2) << 1) | ((g1 & 2) << 0) | ((g0 & 2) >> 1);
uint8_t c3 = ((g3 & 1) << 3) | ((g2 & 1) << 2) | ((g1 & 1) << 1) | ((g0 & 1) << 0);
accessBitBuffer[0] = (~c2 & 0xF) << 4 | (~c1 & 0xF);
accessBitBuffer[1] = c1 << 4 | (~c3 & 0xF);
accessBitBuffer[2] = c3 << 4 | c2;
} // End MIFARE_SetAccessBits()
bool try_key_a(MIFARE_Key *key)
{
bool result = false;
uint8_t buffer[18];
uint8_t block = START_BLOCK + 3;
status_code status;
status = pcd_authenticate(PICC_CMD_MF_AUTH_KEY_A, block, key, get_uid());
if (status != STATUS_OK) {
return false;
}
// Read block
uint8_t byteCount = sizeof(buffer);
status = mifare_read(block, buffer, &byteCount);
if (status != STATUS_OK) {
}
else {
// Successful read
result = true;
}
//stop_card_working();
return result;
}
bool try_key_b(MIFARE_Key *key)
{
bool result = false;
uint8_t buffer[18];
uint8_t block = START_BLOCK + 3;
status_code status;
status = pcd_authenticate(PICC_CMD_MF_AUTH_KEY_B, block, key, get_uid());
if (status != STATUS_OK) {
return false;
}
// Read block
uint8_t byteCount = sizeof(buffer);
status = mifare_read(block, buffer, &byteCount);
if (status != STATUS_OK) {
}
else {
// Successful read
result = true;
}
//stop_card_working();
return result;
}
mifaredata_t* read_mifare_card()
{
status_code status;
uint8_t block = START_BLOCK;
uint8_t len = 18;
uint8_t buffer[18];
uint8_t count = 0;
MIFARE_Key key;
for (uint8_t k = 0; k < NR_KNOWN_KEYS; k++) {
for (uint8_t i = 0; i < MF_KEY_SIZE; i++) {
key.keyByte[i] = knownKeys[k][i];
}
if (try_key_a(&key)) {
break;
}
count++;
picc_is_new_card_present();
picc_read_card_serial();
}
if(count == NR_KNOWN_KEYS) {
stop_card_working();
return NULL;
}
for(uint8_t i = 0; i < sizeof(mifare_card_data); i += 16)
{
status = pcd_authenticate(PICC_CMD_MF_AUTH_KEY_A, block, &key, get_uid());
if (status != STATUS_OK) {
return NULL;
}
status = mifare_read(block, buffer, &len);
if (status != STATUS_OK) {
return NULL;
}
block++;
for (uint8_t j = 0; j < 16; j++) {
((uint8_t *)&mifare_card_data)[i + j] = buffer[j];
}
if(block%4 == 3) block++;
}
return &mifare_card_data;
}
bool write_mifare_card()
{
status_code status;
uint8_t block = START_BLOCK;
uint8_t count = 0;
uint8_t trailerBuffer[] = {
255, 255, 255, 255, 255, 255, // Keep default key A
0, 0, 0,
0,
255, 255, 255, 255, 255, 255}; // Keep default key B
for (uint8_t i = 0; i < MF_KEY_SIZE; i++){
trailerBuffer[i] = knownKeys[1][i];
trailerBuffer[i + 10] = knownKeys[1][i];
}
MIFARE_SetAccessBits(&trailerBuffer[6], 4, 4, 4, 1);
MIFARE_Key key;
for (uint8_t k = 0; k < NR_KNOWN_KEYS; k++) {
for (uint8_t i = 0; i < MF_KEY_SIZE; i++) {
key.keyByte[i] = knownKeys[k][i];
}
if (try_key_a(&key)) {
break;
}
picc_is_new_card_present();
picc_read_card_serial();
count++;
}
if(count == NR_KNOWN_KEYS) {
stop_card_working();
return false;
}
for(uint8_t i = 0; i < sizeof(mifare_card_data); i += 16)
{
status = pcd_authenticate(PICC_CMD_MF_AUTH_KEY_B, block, &key, get_uid());
if (status != STATUS_OK) {
return false;
}
status = mifare_write(block, &(((uint8_t *)&mifare_card_data)[i]), 16);
if (status != STATUS_OK) {
return false;
}
block++;
if(block%4 == 3) {
// write security
/*status = pcd_authenticate(PICC_CMD_MF_AUTH_KEY_A, block, &key, get_uid());
if (status != STATUS_OK) {
return false;
}
status = mifare_write(block, &trailerBuffer[0], 16);
if (status != STATUS_OK) {
return false;
}*/
block++;
}
}
//stop_card_working();
return true;
}
void stop_card_working()
{
picc_halt_a();
pcd_stop_cryptol();
}
mifaredata_t* init_mifare_card_data()
{
for(uint8_t i = 0; i < sizeof(mifare_card_data); i++)
{
((uint8_t *)&mifare_card_data)[i] = 0x00;
}
mifare_card_data.init = 0xDEADBEEF;
return &mifare_card_data;
}
bool is_empty_mifare_card()
{
return mifare_card_data.init != 0xDEADBEE0;
}
bool need_clear_bonus()
{
uint32_t SystemTime = GetTimeSec();
if(SystemTime > mifare_card_data.best_before)
{
mifare_card_data.bonus = 0;
return true;
}
return false;
}