# Primitive Component: PRESENT Scrambler

# Overview

`prim_present` is an (unhardened) implementation of the encryption pass of the [64bit PRESENT block cipher](https://en.wikipedia.org/wiki/PRESENT).
It is a fully unrolled combinational implementation that supports both key lengths specified in the paper (80bit and 128bit).
Further, the number of rounds is fully configurable, and the primitive supports a 32bit block cipher flavor which is not specified in the original paper.

It should be noted, however, that reduced-round and/or 32bit versions **are not secure** and must not be used in a setting where cryptographic cipher strength is required.
I.e., this primitive is only intended to be used as a lightweight data scrambling device.

## Parameters

Name          | type   | Description
--------------|--------|----------------------------------------------------------
DataWidth     | int    | Block size, can be 32 or 64
KeyWidth      | int    | Key size, can be 64, 80 or 128
NumRounds     | int    | Number of PRESENT rounds, has to be greater than 0
NumPhysRounds | int    | Number of physically instantiated PRESENT rounds (defaults to NumRounds)

Note that by setting `NumRounds = 31` and `NumPhysRounds = 1` we can construct a PRESENT primitive that is suitable for iterative evaluation of a full-round PRESENT pass, where each iteration evaluates one of the 31 rounds.

## Signal Interfaces

Name         | In/Out | Description
-------------|--------|---------------------------------
data_i       | input  | Plaintext input
key_i        | input  | Key input
idx_i        | input  | Round index input
data_o       | output | Output of the ciphertext
key_o        | output | Key output after keyschedule update
idx_o        | output | Round index output after keyschedule update

The `key_o` and `idx_o` are useful for iterative implementations where the state of the scheduled key, as well as the current round index have to be registered in between rounds.
Note that `idx_i` should be initialized to 1 for encryption mode, and to `NumRounds` for decryption mode.

# Theory of Operations

```
             /---------------\
             |               |
idx_i        |               | idx_o
=====/======>|               |=====/======>
 [5]         |               | [5]
             |    PRESENT    |
key_i        |               | key_o
=====/======>|   DataWidth   |=====/======>
 [KeyWidth]  |   KeyWidth    | [KeyWidth]
             |   NumRounds   |
data_i       | NumPhysRounds |  data_o
=====/======>|               |=====/=======>
 [DataWidth] |               |  [DataWidth]
             |               |
             \---------------/
```

The PRESENT module is fully unrolled and combinational, meaning that it does not have any clock, reset or handshaking inputs.
The only inputs are the key and the plaintext, and the only output is the ciphertext.

The internal construction follows the algorithm described in the original [paper](http://www.lightweightcrypto.org/present/present_ches2007.pdf).
The block size is 64bit and the key size can be either 80bit or 128bit, depending on the security requirements.
In its original formulation, this cipher has 31 rounds comprised of an XOR operation with a round key, followed by the application of an s-box and a permutation layer, as illustrated for the encryption pass below:

```c++
NumRounds = 32;
idx_i = 1;

round_keys = key_derivation(key_i, idx_i);

state = data_i;

for (int i=0; i < NumRounds; i++) {
  state = state ^ round_keys[i];
  state = sbox4_layer(state);
  state = perm_layer(state);
}

data_o = state ^ round_keys[NumRounds-1];
key_o  = round_keys[NumRounds-1];
idx_o  = idx_i + NumRounds;
```

The reduced 32bit block-size variant implemented is non-standard and should only be used for scrambling purposes, since it **is not secure**.
It leverages the same crypto primitives and key derivation functions as the 64bit variant, with the difference that the permutation layer is formulated for 32 instead of 64 elements.
