# Primitive Component: Keccak permutation

# Overview

`prim_keccak`

is a single round implementation of the permutation stage in SHA3 algorithm.
Keccak primitive module assumes the number of rounds is less than or equal to 12 + 2L.
It supports all combinations of the data width described in the spec.
This implementation is not currently hardened against side-channel or fault injection attacks.
It implements the Keccak_p function.

## Parameters

Name | Type | Description |
---|---|---|

Width | int | state width in bits. can be 25, 50, 100, 200, 400, 800, or 1600 |

### Derived Parameters

The parameters below are derived parameter from `Width`

parameter.

Name | Type | Description |
---|---|---|

W | int | number of slices in state. `Width/25` |

L | int | log2 of `W` |

MaxRound | int | maximum allowed round value. `12 + 2L` |

RndW | int | bit-width to represent MaxRound. log2 of `MaxRound` |

## Signal Interfaces

Signal | Type | Description |
---|---|---|

rnd_i | input [RndW] | current round number [0..(MaxRound-1)] |

s_i | input [Width] | state input |

s_o | output[Width] | permutated state output |

`s_i`

and `s_o`

are little-endian bitarrays.
The SHA3 spec shows how to convert the bitstream into the 5x5xW state cube.
For instance, bit 0 of the stream maps to `A[0,0,0]`

.
The bit 0 in the spec is the first bit of the bitstream.
In `prim_keccak`

, `s_i[0]`

is the first bit and `s_i[Width-1]`

is the last bit.

# Theory of Operations

```
| |
rnd_i | |
---/---->| -----------------------------------------\ |
[RndW] | | |
| | |
s_i | V | s_o
===/====>| bit2s() -> chi(pi(rho(theta))) -> iota( ,rnd) -> s2bit() |==/==>
[Width] | |-----------keccak_p--------------| |[Width]
| |
```

`prim_keccak`

implements “Step Mappings” section in SHA3 spec.
It is composed of five unique permutation functions, theta, rho, pi, chi, and iota.
Also it has functions that converts bitstream of `Width`

into `5x5xW`

state and vice versa.

Three constant parameters are defined inside the keccak primitive module. The rotate position described in phi function is hard-coded as below. The value is described in the SHA3 specification.

```
localparam int PiRotate [5][5] = '{
//y 0 1 2 3 4 x
'{ 0, 3, 1, 4, 2},// 0
'{ 1, 4, 2, 0, 3},// 1
'{ 2, 0, 3, 1, 4},// 2
'{ 3, 1, 4, 2, 0},// 3
'{ 4, 2, 0, 3, 1} // 4
};
```

The shift amount in rho function is defined as `RhoOffset`

parameter.
The value is same as in the specification, but it is used as `RhoOffset % W`

.
For instance, `RhoOffset[2][2]`

is 171.
If `Width`

is 1600, the value used in the design is `171%64`

, which is `43`

.

The round constant is calculated by the tool `hw/ip/prim/util/keccak_rc.py`

.
The recommended default value of 24 rounds is used in this design,
but an argument (changed with the `-r`

flag) is provided for reference.
The `keccak_rc.py`

script creates 64 bit of constants and the `prim_keccak`

module uses only lower bits of the constants if the `Width`

is less than 1600.
For instance, if `Width`

is 800, lower 32bits of the round constant are used.