blob: deb188f5a57e905e84902c2b7de5f81caa33fe88 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// sha3_pkg
package sha3_pkg;
// StateW represents the width of Keccak state variable.
// As Sha3 assume the state value as 1600, this shouldn't be modified.
// Note that keccak_round is flexible. It can have any values defined in SHA3
// specification. But sha3pad logic assumes the value as 1600.
parameter int StateW = 1600;
// Function Name (N) and Customzation String (S) shall be
// smaller than 2**256 bits and integer divisiable by 8.
parameter int FnWidth = 32; // up to 32bit Function Name
parameter int CsWidth = 256; // up to 256bit Customization Input
// Calculate left_encode(len( X )) bit size.
// Assume the enc_8(n) is always 1 (up to 255 byte of len(S) size)
// e.g) 248bit --> two bytes , 256bit --> three bytes
// round8bit(clog2(X+1))/8
parameter int MaxFnEncodeSize = ($clog2(FnWidth+1) + 8 - 1) / 8 + 1;
parameter int MaxCsEncodeSize = ($clog2(CsWidth+1) + 8 - 1) / 8 + 1;
parameter int NSRegisterSizePre = FnWidth/8 + CsWidth/8
+ MaxFnEncodeSize + MaxCsEncodeSize;
// Round up to 32bit word base
parameter int NSRegisterSize = ((NSRegisterSizePre + 4 - 1 ) / 4) * 4;
// Prefix represents bytepad(encode_string(N) || encode_string(S), 168 or 136)
// +2 represents left_encoding(168 or 136) which could be either:
// 10000000 || 00010101 // 168
// 10000000 || 00010001 // 136
parameter int PrefixSize = NSRegisterSize + 2;
// index width for `N` and `S`
parameter int PrefixIndexW = $clog2(PrefixSize/64);
// Datapath width in KMAC, this also affects the output of MSG_FIFO
// This is assumed as 64 in KMAC design. If this value is changed, some parts
// of the KMAC design need to be changed.
//
// 1. keccak_round logic datapath. Keccak round logic assumes MsgWidth
// divides 1600 keccak state `Width`. Choose the value accordingly.
// 2. sha3pad module has fixed width mux for funcpad logic. If MsgWidth is
// changed, the logic also need to be revised.
// 3. kmac core logic also has fixed size mux for appeding output length.
// Revise the case statement to fit into revised MsgWidth value.
parameter int MsgWidth = 64;
parameter int MsgStrbW = MsgWidth / 8;
// Keccak module supports SHA3, SHAKE, cSHAKE function.
// This mode determines if the module uses encoded N and S or not.
// Also it chooses the padding value.
//
// mode | little-endian
// -------|----------------
// Sha3 | 2'b 10
// Shake | 4'b 1111
// CShake | 2'b 00
//
// Please remind that if input strings N and S are empty, SW shall
// choose SHAKE even for cSHAKE operation.
typedef enum logic[1:0] {
Sha3 = 2'b 00,
Shake = 2'b 10,
CShake = 2'b 11
} sha3_mode_e;
// keccak_strength_e determines the security strength against collision attack
// This value decides the _rate_ and _capacity_ of the keccak states.
// It affects the sha3pad module too. the padding module implements
// `bytepad(X,168)` for L128, `bytepad(X,136)` for L256 in cSHAKE
typedef enum logic [2:0] {
L128 = 3'b 000, // rate: 1344 bit / capacity: 256 bit Keccak[ 256](, 128)
L224 = 3'b 001, // rate: 1152 bit / capacity: 448 bit Keccak[ 448](, 224)
L256 = 3'b 010, // rate: 1088 bit / capacity: 512 bit Keccak[ 512](, 256)
L384 = 3'b 011, // rate: 832 bit / capacity: 768 bit Keccak[ 768](, 384)
L512 = 3'b 100 // rate: 576 bit / capacity: 1024 bit Keccak[1024](, 512)
} keccak_strength_e;
parameter int unsigned KeccakRate [5] = '{
1344/MsgWidth, // 21 depth := (1600 - 128*2)
1152/MsgWidth, // 18 depth := (1600 - 224*2)
1088/MsgWidth, // 17 depth := (1600 - 256*2)
832/MsgWidth, // 13 depth := (1600 - 384*2)
576/MsgWidth // 9 depth := (1600 - 512*2)
};
parameter int unsigned MaxBlockSize = KeccakRate[0];
parameter int unsigned KeccakEntries = 1600/MsgWidth;
parameter int unsigned KeccakMsgAddrW = $clog2(KeccakEntries);
parameter int unsigned KeccakCountW = $clog2(KeccakEntries+1);
// SHA3 core state. This state value is used in sha3core module
// and also in KMAC top module and the register interface for sw to track the
// sha3 status.
// Encoding generated with:
// $ ./util/design/sparse-fsm-encode.py -d 3 -m 7 -n 6 \
// -s 4082450958 --language=sv
//
// Hamming distance histogram:
//
// 0: --
// 1: --
// 2: --
// 3: |||||||||||||||||||| (57.14%)
// 4: ||||||||||||||| (42.86%)
// 5: --
// 6: --
//
// Minimum Hamming distance: 3
// Maximum Hamming distance: 4
// Minimum Hamming weight: 1
// Maximum Hamming weight: 4
//
localparam int StateWidth = 6;
typedef enum logic [StateWidth-1:0] {
StIdle_sparse = 6'b101100,
// Absorb stage receives the message bitstream and computes the keccak
// rounds. This internal operation is mainly done inside sha3pad module
// not sha3core. The core module and this state machine observe the status
// of the process and mainly waits until all the sponge absorbing is
// completed. The main indicator is `absorbed` signal.
StAbsorb_sparse = 6'b100001,
// TODO: Implement StAbort later after context-switching discussion.
// Abort stage can be moved from StAbsorb stage. It basically holds the
// keccak round operation and opens up the internal state variable to the
// software. This stage is for the software to pause current operation and
// store the internal state elsewhere then initiates new KMAC/SHA3 process.
// StAbort only can be moved to _StFlush_.
//StAbort_sparse = 6'b011101,
// Squeeze stage allows the software to read the internal state.
// If `EnMasking`, it opens the read permission of two share of the state.
// The squeezing in SHA3 specification describes the software to read up to
// the rate of SHA3 algorithm but this logic opens up the entire 1600 bits
// of the state (3200bits if `EnMasking`).
StSqueeze_sparse = 6'b001011,
// ManualRun stage initiaties the keccak round and waits the completion.
// This state is moved from Squeeze state by writing 1 to manual_run CSR.
// When keccak round is completed, it goes back to Squeeze state.
StManualRun_sparse = 6'b010000,
// Flush stage, the core clears out the internal variables and also
// submodules' variables too. Then moves back to Idle state.
StFlush_sparse = 6'b000110,
StTerminalError_sparse = 6'b111010
} sha3_st_sparse_e;
localparam int StateWidthLogic = 3;
typedef enum logic [StateWidthLogic-1:0] {
StIdle,
StAbsorb,
//StAbort,
StSqueeze,
StManualRun,
StFlush,
StError
} sha3_st_e;
function automatic sha3_st_e sparse2logic(sha3_st_sparse_e st);
unique case (st)
StIdle_sparse : return StIdle;
StAbsorb_sparse : return StAbsorb;
//StAbort_sparse : return StAbort;
StSqueeze_sparse : return StSqueeze;
StManualRun_sparse : return StManualRun;
StFlush_sparse : return StFlush;
default : return StError;
endcase
endfunction : sparse2logic
//////////////////
// Error Report //
//////////////////
typedef enum logic [7:0] {
ErrNone = 8'h 00,
// ErrSha3SwControl occurs when software sent wrong flow signal.
// e.g) Sw set `process_i` without `start_i`. The state machine ignores
// the signal and report through the error FIFO.
ErrSha3SwControl = 8'h 80
} err_code_e;
typedef struct packed {
logic valid;
err_code_e code; // Type of error
logic [23:0] info; // Additional Debug info
} err_t;
///////////////
// Functions //
///////////////
// Bytepading function
// `encode_bytepad_len` represents the first two bytes of bytepad()
// It depends on the block size. We can reuse KeccakRate
// 10000000 || 00010101 // 168
// 10000000 || 00010001 // 136
function automatic logic [15:0] encode_bytepad_len(keccak_strength_e kstrength);
logic [15:0] result;
unique case (kstrength)
L128: result = 16'h A801; // cSHAKE128
L224: result = 16'h 9001; // not used
L256: result = 16'h 8801; // cSHAKE256
L384: result = 16'h 6801; // not used
L512: result = 16'h 4801; // not used
default: result = 16'h 0000;
endcase
return result;
endfunction : encode_bytepad_len
endpackage : sha3_pkg