Cryptography Engineering, Teil 4: AES auf AVR ATmega

Im dritten Teil der Cryptography-Engineering-Serie kristallisierte sich die mathematische Strategie für eine Implementierung auf dem 8-Bit-Mikrocontroller ATmega heraus. Nun gilt es, die Erkenntnisse in C-Code zu gießen und das Ergebnis als Simulation und in Hardware zu betrachten.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 12 Min.
Von
  • Oliver Müller
Inhaltsverzeichnis

Im dritten Teil der Cryptography-Engineering-Serie kristallisierte sich die mathematische Strategie für eine Implementierung auf dem 8-Bit-Mikrocontroller ATmega heraus. Die praktischen Algorithmen ließen sich daraus herleiten. Nun gilt es, die Erkenntnisse in C-Code zu gießen und das Ergebnis als Simulation und in Hardware zu betrachten.

Wie im dritten Teil beschrieben, ist das Implementieren von AES auf den Winzlingen der digitalen Welt – den Mikrocontrollern – eine Herausforderung. Als gangbarer Weg kristallisierte sich zusammenfassend heraus:

Mehr Infos

Cryptography Engineering

Die Artikel zur Reihe:

  1. Zur Theorie des AES
  2. AES-Implementierung für PC- und Serversysteme
  3. AES-Implementierung für 8-Bit-Microcontroller
  4. AES-Implementierung auf AVR ATmega
  5. AES-Implementierung für mobile Endgeräte (Android)
  1. Die S-Boxen lassen sich mit dem erweiterten Euklidischen Algorithmus berechnen. Sie belasten somit die kostbaren Speicherressourcen des EEPROM (Electrically Erasable Programmable Read-Only Memory) und des RAM nicht.
  2. Die Schlüsselexpansion erfolgt beim Booten des Mikrocontrollers. Die einzelnen Rundenschlüssel liegen nicht bereits expandiert als Array im EEPROM. Ein Ablegen der expandierten Schlüssel im EEPROM würde zwar das RAM entlasten, aber die Ver- und Entschlüsselungszeiten durch Synchronisierungszeiten des EEPROM in die Höhe treiben.
Mehr Infos

Quellcode

Hinweis: Die Sourcen zu diesem Artikel finden Sie im Tarball auf dem heise Developer FTP zum Download.

Das Projekt aes8bit.aws aus Verzeichnis avr ist für AVR Studio 4 ausgelegt. Es implementiert ein kleines Beispielprogramm für einen ATmega32. Die eigentliche Implementierung von AES liegt in aes.c. Bis auf die Tatsache, dass sie auf reines C und 8-Bit-Operationen heruntergebrochen ist, hält sie gegenüber der Implementierung aus dem zweiten Teil keine Überraschungen bereit. Typisch für Mikrocontroller-Code ist das Verwenden globaler Variablen, die das Software Engineering auf den großen Systemen (dort zu Recht) scheut wie der Teufel das Weihwasser.

Der Schlüssel liegt im internen EEPROM des AVR im Array ee_key. Zusätzlich sind dort auch die Rundenanzahl und damit indirekt die Länge des AES-Schlüssels als ee_rnum abgelegt. Beim Booten ruft das System die Routine aes_init() auf, die den Schlüssel über den bekannten, in expandKey() implementierten Algorithmus expandiert. expandKey() lädt hierzu den Schlüssel und die Rundenanzahl aus dem EEPROM per eeprom_read_byte(). Die Expansion des Schlüssels erfolgt in das Array key im RAM. Der Inhalt des EEPROM mit einem Beispielschlüssel liegt im Übrigen separat im Modul eeprom.c.

Die neuen Algorithmen zum dynamischen Berechnen der S-Box-Einträge liegen in den Funktionen gdeg() und gmulinv(). Sie implementieren eins zu eins die Algorithmen aus Abbildung 1. Die restliche Implementierung in aes.c ist lediglich eine für 8-Bit-Operationen ausgelegte Variante der 32-Bit-Implementierung aus dem zweiten Teil dieser Artikelreihe.

Optimierte Variante für 8-Bit-Mikrocontroller des Algorithmus zur Berechnung des Inversen in GF(2^8) (Abb. 1)

Für den Praxistest liegt der weiteren AVR-Implementierung eine einfache Schaltung analog zum Schaltplan in Abbildung 2 zugrunde. Neben der "Grundbeschaltung" aus Reset-Taster, ISP-Interface fürs "In System Programming" und externer Taktversorgung mit 16 MHz verfügt der eingesetzte ATmega32 über eine serielle Schnittstelle (USART) und einige LEDs. Die USART-Pfostenleiste erwartet ein FTDI-USB-nach-seriell-Kabel, das die Verbindung zwischen PC und AVR-System herstellt. Über den USB-Bus bezieht die Schaltung zudem im Normalbetrieb ihre Stromversorgung. Beim Programmieren über ISP erhält sie ihren Strom alternativ über den ISP-Bus.

Schaltplan des Experimentierboards (Abb. 2)

Das Modul usart.c übernimmt die Anbindung der seriellen Schnittstelle. Es lässt sich per usart_init() mit einer übergebenen Baudrate initialisieren. Das Modul liest dann per Interrupt über den Handler ISR(USART_RXC_vect) eingehende Zeichen in den Ringpuffer rbuff ein. Die eingelesenen Zeichen lassen sich per usart_getc() aus der Anwendung auslesen. Sie arbeitet im "Blocking I/O-Mode". Mit usart_puts() lassen sich Strings über die serielle Schnittstelle ausgeben. Näheres zum Ansteuern der seriellen Schnittstelle lässt sich Florian Schäffers Buch "AVR: Hardware und C-Programmierung in der Praxis" entnehmen.

Die LEDs am Port A des ATmega symbolisieren zwei Ampeln einer Kreuzung. Der ATmega fungiert als Ampelsteuerung für diese Kreuzung. Die Steuerung der Ampeln erfolgt im Modul traffic.c. Es nutzt den 16-Bit-Timer TIMER1 des ATmega32, um zwischen den einzelnen Zuständen der Ampeln zu wechseln. Bei jedem Überlauf des Timer-Counters erfolgt ein Wechsel des Ampellichts in der Interrupt-Routine ISR(TIMER1_OVF_vect). Die Geschwindigkeit des Wechsels bestimmt der aktuell gesetzte Prescaler des Timers. Die normalen Zustände beider Ampeln sind an den Indizes 0 bis 5 des globalen Arrays control abgelegt. Im normalen Betrieb durchläuft das System diese sechs Zustände zyklisch; schaltet also die Ampeln wechselnd auf rot und grün mit den entsprechenden Zwischenzuständen rotgelb und gelb. Der Zustand "beide auf rot" ist zum "Abschalten" der Kreuzung gedacht. Neben noch einigen Zuständen zum "weichen Anfahren" der Ampeln gibt es noch den "Stirb langsam 4.0"-Zustand. Er verursacht Chaos und schaltet alle Ampeln auf grün. Doch dazu später mehr.