Sicherheits-Dongle mit EEPROM – Ein Passwort zum Mitnehmen

Auf der Suche nach einem greifbaren Beispiel für die Verwendung eines EEPROMs, kam

EEPROM_Dongle_2

ich auf eine Idee. Ich habe auf einer kleinen Platine ein I²C EEPROM verbaut und mit einem Steckanschluss ausgestattet. Im EEPROM sind einige Zellen mit bestimmten

Werten beschrieben. Das dazugehörige Programm prüft nun ob alle Zellen mit dem vorab definierten „Passcode“ übereinstimmen. Nur dann startet das Programm, bzw. führt Aktionen aus. Also quasi ein Passwort für die Hosentasche.

Wie das Ganze funktioniert versuche ich nun einmal zu erläutern.

Vorbereitung des Raspberry Pi

Zuerst werden, wie auch im I²C Beitrag von mir beschrieben, die I²C Funktion aktiviert und die Pakete „i2c-tools“ und „smbus“ installiert.

Freischalten der I²C Treiber

raspi-blacklist.conf bearbeiten per:

sudo nano /etc/modprobe.d/raspi-blacklist.conf

Hier das “#” vor der Zeile

#blacklist i2c-bcm2708

löschen.
Datei speichern und schließen.

Nun die Datei /etc/modules per

sudo nano /etc/modules

öffnen und 2 Zeilen einfügen:

i2c-dev
i2c-bcm2708

Datei speichern und schließen.
Nun in der Shell das Paket “i2c-tools” installieren.

# apt-get update
# apt-get install i2c-tools

Um mit I²C in Python zu arbeiten wird noch das Paket “smbus” benötigt. Auch dies wieder mit dem Paketmanager installieren.

apt-get install python-smbus

 

Das EEPROM

Ein EEPROM ist ein externer Speicherbaustein, der auch nach dem Trennen der Versorgungsspannung seinen Inhalt beibehält. In meinem Beispiel nutze ich das  I²C EEPROM „24C04WP“. Dieses Bauteil hat 4 kB Speicherplatz. Für meine Zwecke deutlich zuviel, aber das tut der Sache keinen Abbruch.eeprom_foto

Das Bauteil hat 8 Beinchen, die wie folgt belegt sind.

  • Pin 1 E0 – Adressierbit
  • Pin 2 E1 – Adressierbit
  • Pin 3 E2 – Adressierbit
  • Pin 4 VSS – Masse
  • Pin 5 SDA
  • Pin 6 SCL
  • Pin 7 WC – Write Control
  • Pin 8 VCC – Versorgungsspannung 3,3V

Die Pins 1-3 können auf Masse oder auf VCC gelegt werden. Je nach Kombination bekommt das EEPROM im I²C Bus eine andere Adresse zugewiesen. Ich möchte aber mit jedem Dongle die gleiche Adresse verwenden, daher habe ich alle drei Pins fest auf Masse gelegt. Pin 5 wird and Pin 3 des Raspberry Pi angeschlossen (SDA), Pin 6 des EEPROM wird mit Pin 5 des Raspberry Pi verbunden (SCL). Der Pin „Write Control“, kann an jeden beliebigen GPIO Pin, an VCC, oder Masse angeschlossen werden. Liegt an WC ein High-Signal an, so kann das EEPROM beschrieben werden. Ist der Pin auf Low, so besteht quasi ein Schreibschutz. Für meine Zwecke, habe ich den Pin auf VCC gelegt um das EEPROM jederzeit zu beschreiben.

EEPROM auslesen

Das Auslesen des EEPROMs funktioniert mit den i²c-tools problemlos.

In der Shell mit diesem Befehl:

i2cget -y 1 0x01
  •  -y 1 wird gewählt bei RPi Rev 2. -y 0 bei der alten Rev 1
  • 0x01 ist die Adresse des Bytes das ausgelesen werden soll

Als Ergebnis sollte nun der Inhalt der Zelle angezeigt werden. Im Rohzustand „0xFF“ oder entsprechend „255“.

Zum Beschreiben wird der Befehl i²cset wie folgt verwendet

i2cset -y 1 0x01 0x0a
  •  Zelle 0x01 wird mit dem Wert 0x0a gefüllt und bleibt ab jetzt im EEPROM gespeichert

Das Python Programm

Damit der Dongle seine Funktion bekommt, habe ich ein kleines Python Programm geschrieben.

eeprom.py

#! /usr/bin/python
import smbus
import time
import RPi.GPIO as GPIO

x = 0
led = 11

start = 0x01
ende = 0x04  

b = smbus.SMBus(1)
address = 0x50 

GPIO.setmode(GPIO.BOARD)
GPIO.setup(led,GPIO.OUT)

def get(cell):
    read = b.read_byte_data(address,cell)
    return read

pw = {1:0x05, 2:0x03, 3: 0x05}

for i in range(start,ende):
    try:
        r=get (i)
    except:
        print  "Dongle anschliessen!"
        break

    if r == pw[i]:
        print "Zelle ",hex(i), " ok"
        x = x+1

    else:
        print "Zelle ",hex(i), " abweichend, Kein Zugriff!"
        x = 0
        break

if x == 3:

    GPIO.output(led, True)
    print "Alles ok, LED an!"
    time.sleep(5)
GPIO.cleanup()

 Was passiert hier?

Ist der Dongle also richtig angeschlossen, so wird in der ersten for-Schleife der Inhalt der ersten drei Zellen ausgelesen. Stimmt jede Zelle mit dem Wert der in dem Dictionary „pw“ definiert ist überein, so zählt die Variable „x“ um Eins hoch. Stimmt eine der Zellen nicht überein, so wird „x“ auf 0 gesetzt und das Programm mit dem Hinweis auf die falsche Zelle beendet. Sind alle 3 Werte passend und „x“ erreicht den Wert 3, so wird der Programmcode ausgeführt, der durch den Dongle geschützt werden soll. In meinem Fall wird ein GPIO Ausgang gesetzt.

Diese Anwendung dient lediglich als Beispiel, natürlich kann der nötige Code im Klartext dem Python Programm entnommen werden. Für ernsthafte Anwendungen muss hier natürlich nachgebessert werden, oder der Zugriff auf den Quellcode verhindert werden. Denkbar ist auch das Speichern der Werte in einer SQL Datenbank. So können sogar mehrere „Benutzer“ anhand des Dongles identifiziert werden.

Das „Admin-Tool“

Natürlich muss vor der Anwendung des Dongles dieser programmiert werden. Das erfolgt entweder „per Hand“ mit den i²c-tools, oder durch ein weiteres Python Programm:

set_dongle.py

#! /usr/bin/python
import smbus
import time

b = smbus.SMBus(1)
address = 0x50 
cell1 = 0x01
cell2 = 0x02
cell3 = 0x03

def set(cell,data):
    write = b.write_byte_data(address,cell,data)
    return    

data1 = input ("Wert 1: ")
data2 = input ("Wert 2: ")
data3 = input ("Wert 3: ")

try:
    set (cell1,data1)
    time.sleep(0.1)
    set (cell2,data2)
    time.sleep(0.1)
    set (cell3,data3)

    print "Alle Zellen erfolgreich beschrieben"
except:
    print "Kommunikationsfehler"

Die Funktion dieses Codes ist simpel. Nach dem Start des Programms, werden drei Werte abgefragt. Diese Werte sind der „Zugangscode“. Solang keine SQL Datenbank verwendet wird, müssen die hier eingegebenen Werte auch im Dictionary „pw“ im Hauptprogramm angepasst werden. Es können hier Werte im Hex-Format z.B. „0x89“, oder als normale Dezimalzahl angegeben werden. Beim Schreiben ins EEPROM, werden die Dezimalwerte automatisch als Hex gesendet.

Sind die drei gewünschten Werte eingegeben, so werden sie mit der Funktion „set()“ ans EEPROM geschickt. Die zu beschreibenen Zellen wurden anfangs in den Variablen „cell1-cell3“ definiert. Die „try – except“ – Klammer beendet das Programm, bzw. zeigt an wenn kein Dongle angesteckt ist, oder ein anderer Fehler beim Schreiben auftritt.

Da ich für diesen Dongle genau vier Leitungen benötige, könnte hier als Verbindung sogar ein USB-Stecker genutzt werden. Präpariert man USB-Stecker und Buchse so, dass die beiden Datenleitungen durch SDA und SCL ersetzt werden, so sieht das Teil sogar noch etwas schöner aus. Die LED auf dem Foto hat nicht die Funktion, für die sie gedacht war. Sie hängt mit einem großen Vorwiderstand an der SDA Leitung, in der Hoffnung ich könnte die Aktivitäten auf dem I²C Bus in einem Flackern der LED wahrnehmen. Kann ich leider nicht 😉 Die LED leuchtet, sobald der Dongle angeschlossen wird… Auch nett.

Das war auch schon das ganze Kunstwerk. Den Umgang mit einem EEPROM erlernt (jedenfalls halbwegs) und eine einigermaßen sinnvolle, praktische Anwendung gebaut.

Ich hoffe Ihr konntet der Sache folgen und mit diesem Tutorial etwas anfangen. Anbei noch ein paar Bilder und Screenshots des Dongle.

 

EEPROM_Dongle eeprom_py set_eeprom_py

Kommentar verfassen