Trabukh
15.01.2011, 04:24
Hallo zusammen,
ich versuche gerade, mittels eines ATmega8 eine SLE4442-Emulation zu entwerfen. Gleich vorweg: Nein, ich versuche nicht, irgendwelche Sonnenstudios, TV-Receiver, Waschautomaten oder sonstiges zu hacken. :wink: Die Emulation ist Teil einer freiwilligen Projektarbeit an der Uni (Thema "Sicherheit und Datenschutz").
Jedenfalls bin ich soweit eigentlich fertig, die Programmierung anhand des Datenblattes zur Karte war rein von der funktionalen Seite betrachtet kein großes Drama, allerdings befürchte ich, dass mein Code schlicht zu langsam ist. Mit dem USB-Kartenleser funktioniert meine "Karte" nämlich wunderbar, im Zielsystem (welches etwa 3.5 mal so schnell arbeitet) geht nichts mehr.
Ein mit 8 MHz getakteter ATmega8 sollte mit den 71.4 KHz Taktfrequenz des Systems meiner Meinung nach ohne jegliche Probleme zurechtkommen. :( Eventuell hab' ich auch einfach irgendwo etwas übersehen oder Mist gebaut, das will ich natürlich nicht ausschließen... ;)
Der Code ist zugegebenermaßen nicht überufernd kommentiert, aber alle wichtigen Funktionen des Datenblattes sollten sofort ersichtlich sein.
Falls jemand eine Idee oder allgemeine Kritik zum Code hat, bin ich für jeden Beitrag dankbar.
Gruß und gute Nacht!
Trabukh
// main.c
//
// cpu: ATMega8
// speed: 8 MHz
#include "sle4442.h"
#include "memory.h"
void edgeFalling() {
switch (mode) {
case MODE_ATR:
// Answer-to-Reset
if (pointerByte <= 3) {
setOutput();
setIO(memoryMain[pointerByte] & (1 << pointerBit));
} else { // ATR finished
setInput();
setMode(MODE_IDLE);
}
break;
case MODE_DATA:
// Outgoing Data Mode
switch (command[0]) {
case 0x30: // Read Main Memory
if (pointerByte <= 255) {
setIO(memoryMain[pointerByte] & (1 << pointerBit));
setOutput();
} else { // Reading finished
setInput();
setMode(MODE_IDLE);
}
break;
case 0x34: // Read Protection Memory
if (pointerByte <= 3) {
setIO(memoryProtected[pointerByte * 8 + pointerBit]);
setOutput();
} else { // Reading finished
setInput();
setMode(MODE_IDLE);
}
break;
case 0x31: // Read Security Memory
if (pointerByte <= 3) {
if ((unlocked == 3) | (pointerByte == 0x00))
setIO(memorySecurity[pointerByte] & (1 << pointerBit));
else
setIO(0);
setOutput();
} else { // Reading finished
setInput();
setMode(MODE_IDLE);
}
break;
}
break;
case MODE_PROC:
// Processing Mode
switch (command[0]) {
case 0x39: // Update Security Memory
setIO(0);
setOutput();
if (unlocked == 3) {
memorySecurity[command[1]] = command[2];
memorySecurity[0x00] &= 0x07;
} else if ((command[1] == 0x00) & (command[2] < memorySecurity[0x00]))
memorySecurity[0x00] = command[2];
waitCycles(124);
setInput();
setMode(MODE_IDLE);
break;
case 0x33: // Compare Verification Data
setIO(0);
setOutput();
if ((memorySecurity[command[1]] == command[2]) & (memorySecurity[0x00] != 0x00)) {
unlocked++;
if (unlocked >= 3) {
unlocked = 3;
memorySecurity[0x00] = 0x07;
}
} else
unlocked = 0;
waitCycles(2);
setInput();
setMode(MODE_IDLE);
break;
case 0x3C: // Write Protection Memory
setIO(0);
setOutput();
if ((unlocked == 3) & (memoryMain[command[1]] == command[2])) {
memoryProtected[command[1]] = 1;
}
waitCycles(124);
setInput();
setMode(MODE_IDLE);
break;
case 0x38: // Update Main Memory
setIO(0);
setOutput();
if (unlocked == 3)
memoryMain[command[1]] = command[2];
waitCycles(124);
setInput();
setMode(MODE_IDLE);
break;
}
break;
}
}
void edgeRising(bool bit) {
// Increase pointers
pointerBit++;
if (pointerBit > 7) {
pointerByte++;
pointerBit = 0;
}
switch (mode) {
case MODE_IDLE:
// Idle Mode - Waiting for command
loop_until_bit_is_clear(PIN,PIN_IO);
pointerByte = 0;
pointerBit = -1;
setMode(MODE_CMD);
break;
case MODE_CMD:
// Command Mode
if (pointerByte <= 2) {
if (bit)
command[pointerByte] |= (1 << pointerBit);
else
command[pointerByte] &= ~(1 << pointerBit);
} else {
loop_until_bit_is_set(PIN,PIN_IO);
pointerByte = 0;
pointerBit = 0;
switch (command[0]) {
case 0x30: // Read Main Memory
pointerByte = command[1];
case 0x34: // Read Protection Memory
case 0x31: // Read Security Memory
setMode(MODE_DATA);
break;
case 0x39: // Update Security Memory
case 0x33: // Compare Verification Data
case 0x3C: // Write Protection Memory
case 0x38: // Update Main Memory
setMode(MODE_PROC);
break;
}
}
break;
}
}
// Clock interrupt
ISR(INT0_vect)
{
if (!(PIN & (1 << PIN_CLK)))
edgeFalling();
else
edgeRising(PIN & (1 << PIN_IO));
}
// Reset interrupt
ISR(INT1_vect)
{
setMode(MODE_ATR);
pointerByte = 0;
pointerBit = 0;
unlocked = 0;
edgeFalling();
}
int main(void) {
// Activate interrupts
MCUCR |= (1 << ISC00) | (1 << ISC11);
GICR |= (1 << INT0) | (1 << INT1);
sei();
// Initialize port
PORT = 0x00;
DDR = 0x00;
PIN = 0x00;
setMode(MODE_ATR);
for (;;) {
;
}
}
// sle4442.h
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
// Global variables
volatile unsigned char mode;
volatile unsigned char unlocked = 0;
// Pin/Port configuration
#define PIN_CLK PD2 // INT0
#define PIN_RST PD3 // INT1
#define PIN_IO PD4
#define PORT PORTD
#define PIN PIND
#define DDR DDRD
// Some helpful functions
bool getReset() {
return PIN & (1 << PIN_RST);
}
void setOutput() {
DDR |= (1 << PIN_IO);
}
void setInput() {
DDR &= ~(1 << PIN_IO);
}
void setIO(bool b) {
if (b)
PORT |= (1 << PIN_IO);
else
PORT &= ~(1 << PIN_IO);
}
void setMode(unsigned char m) {
mode = m;
}
void waitCycles(unsigned char c) {
for (unsigned char i = 0; i < c; i++) {
loop_until_bit_is_set(PIN,PIN_CLK);
loop_until_bit_is_clear(PIN,PIN_CLK);
}
}
// Mode constants
#define MODE_ATR 1
#define MODE_CMD 2
#define MODE_DATA 3
#define MODE_PROC 4
#define MODE_IDLE 5
// Memory pointers
volatile unsigned int pointerByte = 0;
volatile signed char pointerBit = 0;
// Command bytes
unsigned char command[3];
// memory.h
unsigned char memoryMain[256] = {
0xA2, 0x13, 0x10, 0x91, 0x46, 0x0B, 0x81, 0x15, 0x42, 0x45, 0x00, 0x30, 0x03, 0x09, 0xED, 0xEA, 0x40, 0x12, 0xFF, 0xFF, 0xFF, 0xD2, 0x76,
0x00, 0x00, 0x63, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x30, 0x32, 0x37, 0x33, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x0A,
0x00, 0xBC, 0x64, 0x64, 0x00, 0x01, 0x00, 0x35, 0xF8, 0xD6, 0x19, 0x00, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x1A, 0x7C, 0x02, 0x05,
0x10, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x66, 0x09, 0x01, 0x14, 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x10, 0xDA,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF };
bool memoryProtected[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 };
unsigned char memorySecurity[] = { 0b00000111, 0xCD, 0x95, 0xE4 }; // Last 3 bytes = PSC
ich versuche gerade, mittels eines ATmega8 eine SLE4442-Emulation zu entwerfen. Gleich vorweg: Nein, ich versuche nicht, irgendwelche Sonnenstudios, TV-Receiver, Waschautomaten oder sonstiges zu hacken. :wink: Die Emulation ist Teil einer freiwilligen Projektarbeit an der Uni (Thema "Sicherheit und Datenschutz").
Jedenfalls bin ich soweit eigentlich fertig, die Programmierung anhand des Datenblattes zur Karte war rein von der funktionalen Seite betrachtet kein großes Drama, allerdings befürchte ich, dass mein Code schlicht zu langsam ist. Mit dem USB-Kartenleser funktioniert meine "Karte" nämlich wunderbar, im Zielsystem (welches etwa 3.5 mal so schnell arbeitet) geht nichts mehr.
Ein mit 8 MHz getakteter ATmega8 sollte mit den 71.4 KHz Taktfrequenz des Systems meiner Meinung nach ohne jegliche Probleme zurechtkommen. :( Eventuell hab' ich auch einfach irgendwo etwas übersehen oder Mist gebaut, das will ich natürlich nicht ausschließen... ;)
Der Code ist zugegebenermaßen nicht überufernd kommentiert, aber alle wichtigen Funktionen des Datenblattes sollten sofort ersichtlich sein.
Falls jemand eine Idee oder allgemeine Kritik zum Code hat, bin ich für jeden Beitrag dankbar.
Gruß und gute Nacht!
Trabukh
// main.c
//
// cpu: ATMega8
// speed: 8 MHz
#include "sle4442.h"
#include "memory.h"
void edgeFalling() {
switch (mode) {
case MODE_ATR:
// Answer-to-Reset
if (pointerByte <= 3) {
setOutput();
setIO(memoryMain[pointerByte] & (1 << pointerBit));
} else { // ATR finished
setInput();
setMode(MODE_IDLE);
}
break;
case MODE_DATA:
// Outgoing Data Mode
switch (command[0]) {
case 0x30: // Read Main Memory
if (pointerByte <= 255) {
setIO(memoryMain[pointerByte] & (1 << pointerBit));
setOutput();
} else { // Reading finished
setInput();
setMode(MODE_IDLE);
}
break;
case 0x34: // Read Protection Memory
if (pointerByte <= 3) {
setIO(memoryProtected[pointerByte * 8 + pointerBit]);
setOutput();
} else { // Reading finished
setInput();
setMode(MODE_IDLE);
}
break;
case 0x31: // Read Security Memory
if (pointerByte <= 3) {
if ((unlocked == 3) | (pointerByte == 0x00))
setIO(memorySecurity[pointerByte] & (1 << pointerBit));
else
setIO(0);
setOutput();
} else { // Reading finished
setInput();
setMode(MODE_IDLE);
}
break;
}
break;
case MODE_PROC:
// Processing Mode
switch (command[0]) {
case 0x39: // Update Security Memory
setIO(0);
setOutput();
if (unlocked == 3) {
memorySecurity[command[1]] = command[2];
memorySecurity[0x00] &= 0x07;
} else if ((command[1] == 0x00) & (command[2] < memorySecurity[0x00]))
memorySecurity[0x00] = command[2];
waitCycles(124);
setInput();
setMode(MODE_IDLE);
break;
case 0x33: // Compare Verification Data
setIO(0);
setOutput();
if ((memorySecurity[command[1]] == command[2]) & (memorySecurity[0x00] != 0x00)) {
unlocked++;
if (unlocked >= 3) {
unlocked = 3;
memorySecurity[0x00] = 0x07;
}
} else
unlocked = 0;
waitCycles(2);
setInput();
setMode(MODE_IDLE);
break;
case 0x3C: // Write Protection Memory
setIO(0);
setOutput();
if ((unlocked == 3) & (memoryMain[command[1]] == command[2])) {
memoryProtected[command[1]] = 1;
}
waitCycles(124);
setInput();
setMode(MODE_IDLE);
break;
case 0x38: // Update Main Memory
setIO(0);
setOutput();
if (unlocked == 3)
memoryMain[command[1]] = command[2];
waitCycles(124);
setInput();
setMode(MODE_IDLE);
break;
}
break;
}
}
void edgeRising(bool bit) {
// Increase pointers
pointerBit++;
if (pointerBit > 7) {
pointerByte++;
pointerBit = 0;
}
switch (mode) {
case MODE_IDLE:
// Idle Mode - Waiting for command
loop_until_bit_is_clear(PIN,PIN_IO);
pointerByte = 0;
pointerBit = -1;
setMode(MODE_CMD);
break;
case MODE_CMD:
// Command Mode
if (pointerByte <= 2) {
if (bit)
command[pointerByte] |= (1 << pointerBit);
else
command[pointerByte] &= ~(1 << pointerBit);
} else {
loop_until_bit_is_set(PIN,PIN_IO);
pointerByte = 0;
pointerBit = 0;
switch (command[0]) {
case 0x30: // Read Main Memory
pointerByte = command[1];
case 0x34: // Read Protection Memory
case 0x31: // Read Security Memory
setMode(MODE_DATA);
break;
case 0x39: // Update Security Memory
case 0x33: // Compare Verification Data
case 0x3C: // Write Protection Memory
case 0x38: // Update Main Memory
setMode(MODE_PROC);
break;
}
}
break;
}
}
// Clock interrupt
ISR(INT0_vect)
{
if (!(PIN & (1 << PIN_CLK)))
edgeFalling();
else
edgeRising(PIN & (1 << PIN_IO));
}
// Reset interrupt
ISR(INT1_vect)
{
setMode(MODE_ATR);
pointerByte = 0;
pointerBit = 0;
unlocked = 0;
edgeFalling();
}
int main(void) {
// Activate interrupts
MCUCR |= (1 << ISC00) | (1 << ISC11);
GICR |= (1 << INT0) | (1 << INT1);
sei();
// Initialize port
PORT = 0x00;
DDR = 0x00;
PIN = 0x00;
setMode(MODE_ATR);
for (;;) {
;
}
}
// sle4442.h
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
// Global variables
volatile unsigned char mode;
volatile unsigned char unlocked = 0;
// Pin/Port configuration
#define PIN_CLK PD2 // INT0
#define PIN_RST PD3 // INT1
#define PIN_IO PD4
#define PORT PORTD
#define PIN PIND
#define DDR DDRD
// Some helpful functions
bool getReset() {
return PIN & (1 << PIN_RST);
}
void setOutput() {
DDR |= (1 << PIN_IO);
}
void setInput() {
DDR &= ~(1 << PIN_IO);
}
void setIO(bool b) {
if (b)
PORT |= (1 << PIN_IO);
else
PORT &= ~(1 << PIN_IO);
}
void setMode(unsigned char m) {
mode = m;
}
void waitCycles(unsigned char c) {
for (unsigned char i = 0; i < c; i++) {
loop_until_bit_is_set(PIN,PIN_CLK);
loop_until_bit_is_clear(PIN,PIN_CLK);
}
}
// Mode constants
#define MODE_ATR 1
#define MODE_CMD 2
#define MODE_DATA 3
#define MODE_PROC 4
#define MODE_IDLE 5
// Memory pointers
volatile unsigned int pointerByte = 0;
volatile signed char pointerBit = 0;
// Command bytes
unsigned char command[3];
// memory.h
unsigned char memoryMain[256] = {
0xA2, 0x13, 0x10, 0x91, 0x46, 0x0B, 0x81, 0x15, 0x42, 0x45, 0x00, 0x30, 0x03, 0x09, 0xED, 0xEA, 0x40, 0x12, 0xFF, 0xFF, 0xFF, 0xD2, 0x76,
0x00, 0x00, 0x63, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x30, 0x32, 0x37, 0x33, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x0A,
0x00, 0xBC, 0x64, 0x64, 0x00, 0x01, 0x00, 0x35, 0xF8, 0xD6, 0x19, 0x00, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x1A, 0x7C, 0x02, 0x05,
0x10, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x66, 0x09, 0x01, 0x14, 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x10, 0xDA,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF };
bool memoryProtected[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 };
unsigned char memorySecurity[] = { 0b00000111, 0xCD, 0x95, 0xE4 }; // Last 3 bytes = PSC