mirror of
https://github.com/dimoniche/solarium.vlad.git
synced 2026-01-30 13:03:30 +03:00
338 lines
8.8 KiB
C
338 lines
8.8 KiB
C
#include "mfrc522data.h"
|
|
#include <includes.h>
|
|
|
|
#include "rfid-spi.h"
|
|
#include "time.h"
|
|
#include "CRC16.h"
|
|
#include "datadesc.h"
|
|
|
|
// äàííûå ñ÷èòàííûå ñ êàðòû
|
|
mifaredata_t mifare_card_data;
|
|
// âàëèäíûå äàííûå àáîíåìåíòà
|
|
abonement_data abonement;
|
|
|
|
#define START_BLOCK 12
|
|
#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));
|
|
}
|
|
|
|
abonement_data* get_abonement_data()
|
|
{
|
|
return &abonement;
|
|
}
|
|
|
|
void set_abonement_data(abonement_data* data)
|
|
{
|
|
memcpy(&abonement, &data, sizeof(abonement_data));
|
|
}
|
|
|
|
uint32_t get_mifare_uid()
|
|
{
|
|
uint32_t card_uid = 0;
|
|
uid_struct * uid = get_uid();
|
|
|
|
if(uid->size == 4)
|
|
{
|
|
memcpy(&card_uid, &uid->uidByte[0], 4);
|
|
}
|
|
|
|
return card_uid;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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++;
|
|
}
|
|
|
|
CPU_INT32U crc1;
|
|
crc1 = crc16((unsigned char*)&mifare_card_data.abonement_data_copy1.init, sizeof(abonement_data) - sizeof(CPU_INT32U));
|
|
|
|
if(crc1 == mifare_card_data.abonement_data_copy1.crc)
|
|
{
|
|
memcpy(&abonement, &mifare_card_data.abonement_data_copy1.init, sizeof(abonement_data));
|
|
}
|
|
else
|
|
{
|
|
CPU_INT32U crc2 = crc16((unsigned char*)&mifare_card_data.abonement_data_copy2.init, sizeof(abonement_data) - sizeof(CPU_INT32U));
|
|
if(crc2 == mifare_card_data.abonement_data_copy2.crc)
|
|
{
|
|
memcpy(&abonement, &mifare_card_data.abonement_data_copy2.init, sizeof(abonement_data));
|
|
}
|
|
else
|
|
{
|
|
for(uint8_t i = 0; i < sizeof(abonement_data); i++)
|
|
{
|
|
((uint8_t *)&abonement)[i] = 0x00;
|
|
}
|
|
}
|
|
}
|
|
|
|
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_b(&key)) {
|
|
break;
|
|
}
|
|
|
|
picc_is_new_card_present();
|
|
picc_read_card_serial();
|
|
|
|
count++;
|
|
}
|
|
|
|
if(count == NR_KNOWN_KEYS) {
|
|
stop_card_working();
|
|
return false;
|
|
}
|
|
|
|
CPU_INT32U crc;
|
|
|
|
memcpy(&mifare_card_data.abonement_data_copy1.init, &abonement, sizeof(abonement_data) - sizeof(CPU_INT32U));
|
|
crc = crc16((unsigned char*)&mifare_card_data.abonement_data_copy1.init, sizeof(abonement_data) - sizeof(CPU_INT32U));
|
|
mifare_card_data.abonement_data_copy1.crc = crc;
|
|
|
|
memcpy(&mifare_card_data.abonement_data_copy2.init, &abonement, sizeof(abonement_data) - sizeof(CPU_INT32U));
|
|
crc = crc16((unsigned char*)&mifare_card_data.abonement_data_copy2.init, sizeof(abonement_data) - sizeof(CPU_INT32U));
|
|
mifare_card_data.abonement_data_copy2.crc = crc;
|
|
|
|
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_B, block, &key, get_uid());
|
|
if (status != STATUS_OK) {
|
|
return false;
|
|
}
|
|
status = mifare_write(block, &trailerBuffer[0], 16);
|
|
if (status != STATUS_OK) {
|
|
return false;
|
|
}
|
|
block++;
|
|
}
|
|
}
|
|
|
|
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(mifaredata_t); i++)
|
|
{
|
|
((uint8_t *)&mifare_card_data)[i] = 0x00;
|
|
}
|
|
|
|
for(uint8_t i = 0; i < sizeof(abonement_data); i++)
|
|
{
|
|
((uint8_t *)&abonement)[i] = 0x00;
|
|
}
|
|
|
|
abonement.init = 0xDEADBEEF;
|
|
|
|
CPU_INT32U password;
|
|
GetData(&PassDescAdmin, &password, 0, DATA_FLAG_SYSTEM_INDEX);
|
|
abonement.uid[0] = password;
|
|
abonement.number_abonement = get_mifare_uid();
|
|
|
|
return &mifare_card_data;
|
|
}
|
|
|
|
bool is_empty_mifare_card()
|
|
{
|
|
bool empty = false;
|
|
|
|
CPU_INT32U crc1, crc2;
|
|
crc1 = crc16((unsigned char*)&mifare_card_data.abonement_data_copy1.init, sizeof(abonement_data) - sizeof(CPU_INT32U));
|
|
crc2 = crc16((unsigned char*)&mifare_card_data.abonement_data_copy2.init, sizeof(abonement_data) - sizeof(CPU_INT32U));
|
|
|
|
if((mifare_card_data.abonement_data_copy1.init != 0xDEADBEEF || crc1 != mifare_card_data.abonement_data_copy1.crc)
|
|
&& (mifare_card_data.abonement_data_copy2.init != 0xDEADBEEF || crc2 != mifare_card_data.abonement_data_copy2.crc)
|
|
)
|
|
{
|
|
empty = true;
|
|
}
|
|
|
|
return empty;
|
|
}
|
|
|
|
bool need_clear_bonus()
|
|
{
|
|
uint32_t SystemTime = GetTimeSec();
|
|
|
|
if(SystemTime > abonement.best_before)
|
|
{
|
|
abonement.bonus = 0;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|