Open Source im professionellen Einsatz

Kernel- und Treiberprogrammierung mit dem Kernel 2.6 – Folge 57

Kern-Technik

,

Texte mit AES verschlüsseln, Daten komprimieren oder Hashsummen mit MD5 berechnen: Mit dem Crypto-API des Linux-Kernels und etwas Know-how kein Problem!

Die umfassende Internetnutzung und das Bedürfnis nach Sicherheit sorgen für stärkere Verbreitung der Kryptographie. Hardwarehersteller bauen aus diesem Grund seit einigen Jahren entsprechende Erweiterungen in die hauseigenen Chips ein, beispielsweise VIA mit Padlock [1] oder Intel mit dem AES-NI-Befehlssatz [2]. Linux wiederum stellt dem Programmierer mit dem Crypto-API Kryptographie-Routinen zur Verfügung, die entweder rein in Software oder aber Hardware-unterstützt ablaufen. Ziel der Kernelentwickler ist es, dies für den Entwickler transparent zu halten.

Das Crypto-API ist nicht nur für Verschlüsselung zuständig, sondern auch für das Bilden von Hash- und Checksummen, für Kompression oder die Generierung von Zufallszahlen. Durch den modularen Aufbau des Crypto-Layers lassen sich auf der unteren Seite die unterschiedlichsten Algorithmen andocken (siehe Tabelle 1), die sich auf der oberen Seite von verschiedenen Subsystemen wie beispielsweise der Festplattenverschlüsselung (DM-Crypt) oder der geschützten VPN-Kommunikation (IPsec) nutzen lassen (siehe Abbildung 1).

Tabelle 1

Unterstützte Krypto-Algorithmen

Funktion

Algorithmen

Hashsummen

md4, md5, michael.mic, ripemd-128, ripemd-160, ripemd-256, ripemd-320, sha1, sha256, sha512, tiger, vmac, whirlpool

Cipher

3des, aead, aes, anubis, arc4, blowfish, camellia, cast5, cast6, des, fcrypt, khazad, salsa20, seed, serpent, tea,xtea,xeta, twofish

Kompression

deflate, lzo, zlib

Sonstiges

ansi_cprng (Pseudo Random Nummer Generator), kernel random number generator, random number generator, crc32c (Checksummen)

Abbildung 1: Der Crypto-Layer des Linux-Kernels abstrahiert Verschlüsselungsalgorithmen.

Transform-Objekte

Basis des Crypto-API im Kernel sind die Transform-Objekte. Für die Bildung von Hashsummen sowie Kompressions- und Verschlüsselungsverfahren gibt es jeweils eigene Objekte. Wenn es um Verschlüsselung geht, hat der Entwickler sogar die Auswahl zwischen vier unterschiedlichen Transforms: Cipher, Blockcipher, Asynchronous Blockcipher und AEAD (Authenticated Encryption with Associated Data). Diese unterscheiden sich bezüglich der Angabe von Quell- und Zielspeicherbereichen und der Funktionalität.

Verstreute Daten

Block-orientierte Transform-Objekte, wozu neben Blockcipher, Asynchronous Blockcipher und AEAD auch Hashsummen gehören, spezifizieren Quelle und Ziel der Operationen auf Basis von Scatter-Gather-Listen (siehe Kasten "Scatter-Gather-Listen"). Stream-orientierte Transforms (Cipher, Compress) verwenden direkt virtuelle Adressen.

Scatter-Gather-Listen

Scatter-Gather-Listen tauchen im Kernel immer dann auf, wenn größere Mengen an Daten zu transferieren sind. Größere Datenmengen – also typischerweise mehr Daten, als in eine so genannte Page (4096 Byte) passen – verteilen sich nämlich im Hauptspeicher häufig über verschiedene physische Adressen.

Scatter-Gather-Listen fassen diese physischen Adressen in einer Datenstruktur zusammen, sodass die Transferfunktionen – etwa das Schreiben der Daten auf die Festplatte – in einem Zug alle notwendigen Informationen besitzen und den Transfer auch per DMA durchführen können. Eigentlich wäre Scatter-Gather-Feld die korrekte Bezeichnung, denn die grundlegende Datenstruktur ist ein Array vom Typ »struct scatterlist«. Jedes Element eines solchen Felds repräsentiert ein zusammenhängendes Fragment im Speicher, das durch eine Page-Adresse, den Startoffset innerhalb der Speicherseite sowie die Länge der dort abgelegten Daten (in Bytes) gekennzeichnet ist.

Ein derartiges Feld kann der Programmierer entweder dynamisch während der Laufzeit allozieren und initialisieren oder dies statisch durch den Compiler erledigen lassen. Im letzteren Fall muss der Code zur Initialisierung »sg_init_table()« aufrufen. Um die einzelnen Feldelemente zu belegen, kommt entweder »sg_set_buf()« oder »sg_set_page()« zum Aufruf – je nachdem, ob die Adresse der Daten als virtuelle oder als Page-Adresse vorliegt. Wurde das Scatter-Gather-Feld per »sg_alloc_table()« angelegt, gibt es »sg_free_table()« nach Gebrauch wieder frei.

Neben den in Tabelle 2 aufgeführten Funktionen gibt es noch eine Reihe weiterer, die insbesondere die Abarbeitung einer Scatter-Gather-Liste vereinfachen.

Tabelle 2

Funktionen zum Aufbau von Scatter/Gather-Listen

Funktionsprototyp

Kurzbeschreibung

int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask);

Reserviert und initialisiert eine Scatter/Gather Liste mit »nents« Feldern. »gfp_mask« gibt den Kontext an, in dem die Funktion aufgerufen wird (User-, Kernel- oder Interrupt-Kontext), »table« enthält nach dem Aufruf die Adresse der Liste.

void sg_init_table(struct scatterlist *sg, unsigned int nents);

Initialisiert die Liste »sg« , die »nents« Einträge hat.

void sg_init_one(struct scatterlist *sg, const void *buf, unsigned int length);

Initialisiert die Liste »sg« (die aus einem einzigen Listenelement besteht) und belegt sie mit der Adresse des Speicherbereiches »buf« und der Länge »length« vor.

static inline void sg_set_page(struct scatterlist *sg, struct page *page, unsigned int len, unsigned int offset);

Initialisiert das Listenelement »sg« mit der Seitenadresses »page« , der Länge »len« und dem Offset »offset« innerhalb der Seite.

static inline void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen);

Initialisiert das Listenelement »sg« mit der virtuellen Adresse »buf« und der Länge »buflen« .

static inline void *sg_virt(struct scatterlist *sg);

Gibt die virtuelle Adresse des Listenelementes »sg« zurück.

Generell arbeiten die Algorithmen synchron, mit dem »ablkcipher«-Transform ist auch eine asynchrone Ver- und Entschlüsselung möglich: Der Crypto-Layer übernimmt Aufträge und übergibt das Ergebnis später per Callback-Funktion dem Auftraggeber. Das AEAD-Transform schließlich kombiniert Verschlüsselung und Hashing, wie es bei IPsec benötigt wird. Vor der Nutzung einer Kryptofunktion im Kernel steht das Anlegen eines geeigneten Transform-Objekts. Dabei ist gleichzeitig der gewünschte Algorithmus anzugeben, beispielsweise »md5«. Vereinfacht ausgedrückt ist hiernach die gewünschte Kryptofunktion mit Übergabe der Quell- und Zielspeicheradressen aufzurufen.

Dass sich der Programmierer im Detail jedoch noch mit Scatter-Gather-Listen, einem Descriptor-Objekt und so etwas wie »digestsize« herumschlagen muss, verdeutlicht dieser Artikel an den Beispielen MD5-Hashsummenbildung und AES-Verschlüsselung.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 5 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Als digitales Abo

Als PDF im Abo bestellen

Ähnliche Artikel

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook