.. _z4-crypt:

==================================
Zadanie 4: Akcelerator szyfrowania
==================================

Data ogłoszenia: 22.12.2020

Termin oddania: 26.01.2021

Archiwum z plikami: :download:`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