Zadanie 4: Akcelerator szyfrowania

Data ogłoszenia: 22.12.2020

Termin oddania: 26.01.2021

Archiwum z plikami: z4_crypt.tar.gz

Napisać układ implementujący akcelerator szyfru TEA (https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm), podłączany do reszty systemu przez AXI.

Układ powinien być sterowany rejestrami MMIO, dostępnymi przez wyrównane pojedyncze 32-bitowe transakcje AXI (wysłanie do układu innych transakcji może powodować odpowiedź SLVERR):

  • 0x40000000, 0x40000004, 0x40000008, 0x4000000c: K[4] — klucz do szyfrowania i odszyfrowywania, dostępny tylko do zapisu (tak, by nie można było z układu wydostać już ustawionego klucza)

  • 0x40000010, 0x40000014: STATE[2] — obecny stan szyfru, używany w niektórych trybach szyfrowania, dostępny do zapisu i odczytu

  • 0x40000018: SRC_ADDR — adres bufora z danymi źródłowych do zaszyfrowania bądź odszyfrowania; powinien być zawsze wyrównany do jednego bloku szyfru (8 bajtów) — bity 0-2 powinny być zawsze równe 0, dostępny do zapisu i odczytu

  • 0x4000001c: DST_ADDR — adres bufora docelowego; jak wyżej

  • 0x40000020: COUNT — liczba bloków do zaszyfrowania bądź odszyfrowania, dostępny do zapisu i odczytu

  • 0x40000024: TRIGGER — rejestr tylko do zapisu, zapis uruchamia akcelerator; ma następujące pola bitowe:

    • bit 0:

      • 0: szyfrowanie

      • 1: deszyfrowanie

    • bity 1-2: tryb szyfru

      • 0: tryb ECB (surowy)

      • 1: tryb CBC

      • 2: tryb CFB

      • 3: tryb CTR32

  • 0x40000028: STATUS — rejestr tylko do odczytu, ma nstępujące pola:

    • 0: BUSY — jeśli 1, akcelerator pracuje i nie należy mu przeszkadzać (czyli dotykać rejestrów poza STATUS); jeśli 0, akcelerator zakończył wszystkie zlecone mu zadania i można wysłać kolejne

    • 1: ERROR — jeśli 1, poprzednie zadanie zakończyło się błędem (któraś wychodząca transakcja AXI zwróciła DECERR bądź SLVERR)

Układ operuje na zasadzie DMA — sam wczytuje dane z pamięci z wybranego adresu za pomocą szyny AXI (zalecana szyna to SAXIHP0) i sam też je tam zapisuje.

Procedura użycia układu jest następująca:

  1. Użytkownik umieszcza dane w buforze źródłowym.

  2. Użytkownik ustawia klucz w rejestrach K[0]..K[3] (może to pominąć, jeśli klucz jest ten sam, co w poprzedniej operacji).

  3. Jeśli używany tryb jest inny niż ECB, użytkownik ustawia wartość początkową (IV) w rejestrach STATE[0], STATE[1] (może to pominąć, jeśli chce kontynuować poprzednią operację).

  4. Użytkownik ustawia adresy buforów i długość operacji w rejestrach SRC_ADDR, DST_ADDR, COUNT.

  5. Użytkownik zapisuje żądany tryb operacji do rejestru TRIGGER, tym samym startując operację.

  6. Urządzenie rozpoczyna pracę, wczytuje bloki danych z bufora SRC_ADDR i zapisuje je do bufora DST_ADDR.

  7. Użytkownik czyta w pętli rejestr STATUS aż bit BUSY będzie równy 0.

  8. Użytkownik zbiera dane z bufora docelowego.

  9. Użytkownik czyta rejestry STATE[0], STATE[1] jeśli zamierza kiedyś kontynuować operację.

Bloki w szyfrze TEA składają się z dwóch 32-bitowych liczb, tutaj zapisanych w formacie little-endian.

Pseudokod przetwarzania bloku dla różnych trybów jest następujący:

  • ECB, szyfrowanie:

    DST = enc(SRC, K)
    
  • ECB, deszyfrowanie:

    DST = dec(SRC, K)
    
  • CBC, szyfrowanie:

    DST = STATE = enc(SRC ^ STATE, K)
    
  • CBC, deszyfrowanie:

    DST = dec(SRC, K) ^ STATE
    STATE = SRC
    
  • CFB, szyfrowanie:

    DST = STATE = SRC ^ enc(STATE, K)
    
  • CFB, deszyfrowanie:

    DST = SRC ^ enc(STATE, K)
    STATE = SRC
    
  • CTR32, szyfrowanie i deszyfrowanie:

    DST = SRC ^ enc(STATE, K)
    STATE[0] += 1