Forum: Mikrocontroller und Digitale Elektronik Kleiner XTEA in C (ohne 32 bit)?


von Dietmar (Gast)


Lesenswert?

Hat jemand eine XTEA-Decipher-Funktion in C, die ohne 32bit-Int 
auskommt? Die drei Zeilen in der for-Schleife unten machen einen 
ATMega-Bootloader leider um 400 Bytes grösser.

// decode 64 bit of data (XTEA with 32 rounds)

#define XTEA_ROUNDS 32
#define XTEA_DELTA  0x9E3779B9

void
decipher(uint32_t v[2])
{
    // 128 bit XTEA key

    static const uint32_t k[4] =
    {
        0x00000000,
        0x00000000,
        0x00000000,
        0x00000000
    };

    uint32_t sum = (XTEA_DELTA * XTEA_ROUNDS);
    uint32_t v0  = v[0];
    uint32_t v1  = v[1];
    uint8_t  i;

    for (i = 0; i < XTEA_ROUNDS; i++)
    {
        v1  -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 
3]);
        sum -= XTEA_DELTA;
        v0  -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
    }

    v[0] = v0; v[1] = v1;
}

von Hagen R. (hagen)


Lesenswert?

Kann nur mit Assembler aushelfen. Dann benötigst du ca. 70 Opcodes = 140 
Bytes. Siehe hier Beitrag "Re: AVR-Bootloader mit Verschlüsselung"
Beachte auch das XTEA eine Blockverschlüsselung ist du benötigst also 
auch einen Ciphermode der über ein Feedback Register den vorherigen 
Block mit dem aktuellen XOR verknüpft. Ansonsten ist es nicht 
cryptographisch sicher. Mein Bootloader benutzt sogar einen 
Doppel-CBC-Feedback-Modus um eine CMAC und 
Alles-Oder-Nichts-Entschlüsselung hinzubekommen um die Authentizität und 
Integrität der entschlüsselten Daten überprüfen zu können.

Gruß Hagen

von Jörg G. (joergderxte)


Lesenswert?

Welchen Compiler verwendest du? (Falls GCC: an "-Os" und "-lm" 
gedacht?).
Bringt es was, wenn du die k-Indexe mit 'passenderen' Datentypen 
berechnest:
1
//statt:
2
/*...*/ (sum + k[(sum>>11) & 3]);
3
//evtl.:
4
(sum + k[ ((uint16_t)sum>>11) & 3 ]);
5
// oder sogar ('sollte' aber nichts mehr bringen):
6
(sum + k[ (uint8_t)((uint16_t)sum>>11) & 3 ]);
Sonst poste eben den (erzeugten!) Assemblercode, vl. faellt da was ins 
Auge

hth, Jörg

von Dietmar (Gast)


Lesenswert?

@Jörg: -lm und -Os werden benutzt. Die vorgeschlagenen Casts sind IMHO 
falsch (das sind 32 bit, die um 11 bit verschoben werden - danach sind 
es immer noch mehr als 16 bit).

@Hagen:
- Assemböer-Code verstehe ich leider nicht.
- Ist das XOR-Verknüpfen die Sahnehaube oder wird der Algorithmus ohne 
diesen Schritt nennswert unsicher?

von Hagen R. (hagen)


Lesenswert?

400 Bytes durch C erzeugten Code ist schon realistisch. Das wird man 
substantiell nur duch Verwendung von handmade Assembler verbessern 
können. Und selbst in Assembler wird man minimal 140 Bytes benötigen. 
Meine XTEA Assembler Routine habe ich schon optimiert und ich sehe keine 
essentiellen Verbesserungsmöglichkeiten mehr. Bei dieser Routine käme in 
einem C Code noch der Overhead hinzu die Register zu sichern und die 
Parameter zu laden.

Gruß Hagen

von Maxxie (Gast)


Lesenswert?

Es ist die Grundlage des Algorithmus (Wie eigentlich bei den meisten 
modernen symetrischen cyphern)
XOR verwendest du in deinem C Code doch auch: ^

von Jörg G. (joergderxte)


Lesenswert?

>@Jörg: -lm und -Os werden benutzt. Die vorgeschlagenen Casts sind IMHO
>falsch (das sind 32 bit, die um 11 bit verschoben werden - danach sind
>es immer noch mehr als 16 bit).
Aber das ist der index für ein Array mit 4 Elementen , nach dem Shift 
sind auch von 16 Bits noch genug für den Index übrig

scnr, Jörg

von Dietmar (Gast)


Lesenswert?

> Es ist die Grundlage des Algorithmus

Es ging nicht um xor im XTEA, sondern um xor der verschlüsselten 64 
bit-Pakete. Ich nehme an, das soll Known-Plaintext-Atacken verhindern?

> Aber das ist der index für ein Array mit 4 Elementen , nach dem Shift
sind auch von 16 Bits noch genug für den Index übrig

Wenn das der Gedanke war, war IMHO die Klammerung falsch. Nicht 
((uint16_t)sum>>11), sondern: (uint16_t)(sum>>11).

Sicher bin ich mir aber nicht, da ich in solchen Fällen immer Klammern 
setze.

So der so, das bringt nichs. Der Code wird sogar länger - vmtl. weil 
irgendeine Optimierung verhindert wird.

von Hagen R. (hagen)


Lesenswert?

>- Ist das XOR-Verknüpfen die Sahnehaube oder wird der Algorithmus ohne
>diesen Schritt nennswert unsicher?

Es ist ein Muß.
Angenommen du benutzt XTEA so wie er ist auf eine 256 Bytes Nachricht 
dann wird durch den XTEA diese 256 Bytes in Blöcke a 8 Bytes getrennt 
voneinander verschlüsselt. Nun gehen wir von folgendem Scenario aus:
Bootloader-Software mit immer gleichen Schlüssel verschlüsselt auf diese 
Weise 10 Programme a 256 Bytes. Ein Angreifer hat nur diese 
verschlüsselten Daten zu Hand aber das Wissen was du gemacht hast. Er 
weis auch das in den ersten 8 Bytes der Programm exakt die Elemente des 
Progammes drinnen stehen die er verändern möchte. Er kann nun ohne 
Probleme die Blöcke der 10 Programme untereinander austauschen und somit 
sein eigenes Program zusammenbauen.

Noch dramatischer wird es wenn wir davon ausgehen würde das es 
verschlüsselte Banküberweisungen sind. Im ersten 8 Bytes Block steht die 
Kontonummer des Empfängers einer Überweisung. Ein Angreifer veranlasst 
dich ihm auf sein Konto Geld zu überweisen und fängt ansonsten jede 
verschlüsselte Bankwüberweisung ab. Nun tauscht er eifach bei jeder 
dieser Überweisungen den ersten 8 Bytes verschlüsselten Datenblock aus 
schwups gehen alle Geldüberweisungen auf sein Konto. Er knackt also 
garnicht den XTEA Algorithmus noch den benutzten Schlüssel sondern 
einfach das benutzte Verfahren wie XTEA kryptographisch falsch benutzt 
wurde.

In meiner Bootloader-Verschlüsselung habe ich das so umgesetzt:
Doppel-CBC-Mode: Die verschlüsselten Daten des letzten Blockes werden 
mit den unverschüsselten Daten des aktuellen Blockes XOR verknüpft. Nun 
wird dieser Block mit XTEA verschlüsselt aber nur die halbe 
Rundenanzahl. Jetzt wird nochmals der aktuelle teilverschlüsselte XTEA 
Datenblock xor-verknüpft mit den verherigen Daten=8 Byte Feedback 
Register. Nun wird die restliche Hälte an Runden mit XTEA verschlüsselt. 
Im Abschlüss wird der verschlüsselte Datenblock in das Feedback Register 
per XOR-Verküpfung eingearbeitet, nicht durch eine einfache 
Kopieroperation. Somit haben wir eine mehrfache Verknüpfung, auch des 
internen Zwischenzustandes der XTEA Verschlüsselung mit einem 
Feedbackregister das über die Datenblöcke hinweg diese fest miteinander 
verbindet. Im Feedback Register entsteht also ein binärer Wert der 
abhängig ist von allen unverschlüsselten Datenblöcken, aller final 
verschlüsselten Datenblöcke und sogar den teilverschlüsselten 
Datenblöcken und damit direkt vom internen Zustandsregister des XTEAs. 
Das alles ist abhängig vom Passwort.

Würde man nun im Ciphertext das höchstwertigste Bit, also das 1. 
Datenbit umkippen und das dann entschlüsseln dann wäre die komplette 
entschlüsselte Nachricht über alle Datenblöcke hinweg zerstört. Also 
eine Alles-Oder-Nichts-Entschlüsselung.

Baut man vor die Daten nun noch 8-16 Bytes Zufall und verschlüsselt 
diese mit den Daten in einem Rutsch dann würde eine Randomisierung des 
Ciphertextes erfolgen. Das ist sowas wie ein externer 
IV=Initialisierungsvektor der aber verschlüsselt ist. Ein und die selbe 
Nachricht mit dem gleichen Passwort mehrfach verschlüsselt würde also 
immer einen komplett anderen Ciphertext ergeben. Logisch da alle 
nachfolgenden Datenblöcke auch vom Inhalt aller vorherigen Datenblöcke 
abhängig verschlüsselt wurden.

Hängt man nun hintendran an die Daten vor der Verschlüsselung eine 
geheime Signatur, zb. 4 Bytes des Passwortes dann hat man damit eine 
CMAC = Cipher Message Authentication. Durch die 
Alles-Oder-Nichts-Entschlüsselung, also die vollständige Propagation von 
Bitfehlern oder Manipulationen am Ciphertext, bzw. die vollständige 
Propagation aller Datenbits der vorherigen Datenblöcke in alle 
nachfolgenden Datenblöcke, wird also auch diese Signatur in einem 
solchen Fall komplett falsch entschlüsselt. Man hat also quasi eine 
kryptograhpisch geschützte Prüfsumme über alle Daten inklusive. 
Normalerweise mürde man mit einer sicheren Hashfunktion einen solche 
"Prüfsumme" erzeugen und diese dann mitliefern. Das kostet aber 
zusätzliche Resourcen im AVR und meine Veränderungen mit dem 
Doppel-CBC-Feedback-Modus ist dagegen fast geschenkt.

Alles in allem macht erst dies eine handvoll krypologischer Angriffe 
unmöglich, Choosen-Plain/Ciphertext Attacks, Reply-Attacks, 
Known-Plaintext-Attacks, Differientielle Kryptoanalyse usw. Gegen all 
diese Verfahren sind Blockverschlüssellungen im ECB Ciphermode (das was 
du vor hattest) nicht resistent.

Und wir haben mit einfachsten Mitteln auch noch eine CMAC. Wir können 
also feststellen ob was schief gegangen ist. Sowohl ob das Passwort das 
benutzt wurde korrekt ist (ohne es zusätzlich zu kompromittieren!), wie 
auch Bitfehler in der Datenübertragung und eben absichtliche 
Manipulationen. Dazu notwendig sind alle oben beschriebenen 
Bestandteile: also Zufallsseed von 8-16 Bytes am Anfang der Daten, der 
Doppel-CBC-Mode und die Teilsignatur bestehend aus dem geheimen Passwort 
am Ende der Daten die dann als eine Nachricht in einem Rutsch 
verschlüsselt werden.

Das alles inklusive ohne zusätzliche kryptographische Funktionen, die 
Resourcen verbrauchen, benutzen zu müssen.

Nicht umsonst habe ich in meinem Bootloader-Thread die Behauptung 
aufgestellt das man nach meinem Wissenstand diesen nur durch Reverse 
Engineering auf Chip Ebene knacken könnte :)

Gruß Hagen

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.