| # Primitive Component: Keccak permutation |
| |
| # Overview |
| |
| `prim_keccak` is a single round implementation of the permutation stage in [SHA3 algorithm][fibs-pub-202]. |
| 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][fibs-pub-202]. |
| This implementation is not currently hardened against side-channel or fault injection attacks. |
| It implements the Keccak_p function. |
| |
| [fibs-pub-202]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf |
| |
| ## 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] | permuted state output |
| |
| `s_i` and `s_o` are little-endian bitarrays. |
| The [SHA3 spec][fibs-pub-202] 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][fibs-pub-202]. |
| 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. |
| |
| ```systemverilog |
| 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. |