#include "mfrc522data.h" #include #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)); } /** * 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; 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; }