| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| // |
| // kmac_pkg |
| |
| package kmac_pkg; |
| parameter int MsgWidth = sha3_pkg::MsgWidth; |
| parameter int MsgStrbW = sha3_pkg::MsgStrbW; |
| |
| // Message FIFO depth |
| // |
| // Assume entropy is ready always (if Share is reused as an entropy in Chi) |
| // Then it takes 72 cycles to complete the Keccak round. While Keccak is in |
| // operation, the module need to store the incoming messages to not degrade |
| // the throughput. |
| // |
| // Based on the observation from HMAC case, the core usually takes 5 clocks |
| // to fetch data and store into KMAC. So the core can push at most 14.5 X 4B |
| // which is 58B. After that, Keccak can fetch the data from MSG_FIFO faster |
| // rate than the core can push. To fetch 58B, it takes around 7~8 cycles. |
| // For that time, the core only can push at most 2 DW. After that Keccak |
| // waits the incoming message. |
| // |
| // So Message FIFO doesn't need full block size except the KMAC case, which |
| // is delayed the operation by processing Function Name N, customization S, |
| // and secret keys. But KMAC doesn't need high throughput anyway (72Mb/s). |
| parameter int RegIntfWidth = 32; // 32bit interface |
| parameter int RegLatency = 5; // 5 cycle to write one Word |
| parameter int Sha3Latency = 72; // Expected masked sha3 processing time 24x3 |
| |
| // Total required buffer size while SHA3 is in processing |
| parameter int BufferCycles = (Sha3Latency + RegLatency - 1)/RegLatency; |
| parameter int BufferSizeBits = RegIntfWidth * BufferCycles; |
| |
| // Required MsgFifoDepth. Adding slightly more buffer for margin |
| parameter int MsgFifoDepth = 2 + ((BufferSizeBits + MsgWidth - 1)/MsgWidth); |
| parameter int MsgFifoDepthW = $clog2(MsgFifoDepth+1); |
| |
| parameter int MsgWindowWidth = 32; // Register width |
| parameter int MsgWindowDepth = 512; // 2kB space |
| |
| // Key related definitions |
| // If this value is changed, please modify the logic inside kmac_core |
| // that assigns the value into `encoded_key` |
| parameter int MaxKeyLen = 512; |
| |
| // size of encode_string(Key) |
| // $ceil($clog2(MaxKeyLen+1)/8) |
| parameter int MaxEncodedKeyLenW = $clog2(MaxKeyLen+1); |
| parameter int MaxEncodedKeyLenByte = (MaxEncodedKeyLenW + 8 - 1) / 8; |
| parameter int MaxEncodedKeyLenSize = MaxEncodedKeyLenByte * 8; |
| |
| // Secret Key left_encode(len(Key)) |
| // ---------- ------------------------ |
| parameter int MaxEncodedKeyW = MaxKeyLen + MaxEncodedKeyLenSize + 8; |
| |
| // key_len is SW configurable CSR. |
| // Current KMAC allows 5 key length options. |
| // This value determines the KMAC core how to map the value |
| // from Secret Key register to key size block |
| typedef enum logic [2:0] { |
| Key128 = 3'b 000, // 128 bit secret key |
| Key192 = 3'b 001, // 192 bit secret key |
| Key256 = 3'b 010, // 256 bit secret key |
| Key384 = 3'b 011, // 384 bit secret key |
| Key512 = 3'b 100 // 512 bit secret key |
| } key_len_e; |
| |
| |
| // kmac_cmd_e defines the possible command sets that software issues via |
| // !!CMD register. This is mainly to limit the error scenario that SW writes |
| // multiple commands at once. |
| typedef enum logic [3:0] { |
| CmdNone = 4'b 0000, |
| CmdStart = 4'b 0001, |
| CmdProcess = 4'b 0010, |
| CmdManualRun = 4'b 0100, |
| CmdDone = 4'b 1000 |
| } kmac_cmd_e; |
| |
| // Timer |
| parameter int unsigned EntropyTimerW = 16; |
| parameter int unsigned EdnWaitTimerW = 16; |
| |
| // Entropy Mode Selection : Should be matched to register package Enum value |
| typedef enum logic [1:0] { |
| EntropyModeNone = 2'h 0, |
| EntropyModeEdn = 2'h 1, |
| EntropyModeSw = 2'h 2 |
| } entropy_mode_e; |
| |
| /////////////////////////// |
| // Application interface // |
| /////////////////////////// |
| |
| // Number of the application interface |
| // Currently KMAC has three interface. |
| // 0: KeyMgr |
| // 1: OTP_CTRL |
| // 2: ROM_CTRL |
| // Make sure to change `width` of app inter-module signal definition |
| // if this value is changed. |
| parameter int unsigned NumAppIntf = 3; |
| |
| // Application Algorithm |
| // Each interface can choose algorithms among SHA3, cSHAKE, KMAC |
| typedef enum bit [1:0] { |
| // SHA3 mode doer not nees any additional information. |
| // Prefix will be tied to all zero and not used. |
| AppSHA3 = 0, |
| |
| // In CShake/ KMAC mode, the Prefix can be determined by the compile-time |
| // parameter or through CSRs. |
| AppCShake = 1, |
| |
| // In KMAC mode, the secret key always comes from sideload. |
| AppKMAC = 2 |
| } app_mode_e; |
| |
| typedef struct packed { |
| app_mode_e Mode; |
| |
| sha3_pkg::keccak_strength_e Strength; |
| |
| // PrefixMode determines the origin value of Prefix that is used in KMAC |
| // and cSHAKE operations. |
| // Choose **0** for CSRs (!!PREFIX), or **1** to use `Prefix` parameter |
| // below. |
| bit PrefixMode; |
| |
| // If `PrefixMode` is 1'b 1, then this `Prefix` value will be used in |
| // cSHAKE or KMAC operation. |
| logic [sha3_pkg::NSRegisterSize*8-1:0] Prefix; |
| } app_config_t; |
| |
| parameter app_config_t AppCfg [NumAppIntf] = '{ |
| // KeyMgr |
| '{ |
| Mode: AppKMAC, // KeyMgr uses KMAC operation |
| Strength: sha3_pkg::L256, |
| PrefixMode: 1'b 0, // Use CSR for prefix |
| Prefix: '0 // Not used in CSR prefix mode |
| }, |
| |
| // OTP |
| '{ |
| Mode: AppCShake, |
| Strength: sha3_pkg::L256, |
| PrefixMode: 1'b 1, // Use prefix parameter |
| Prefix: 'h 0 // TODO: Determine the prefix value |
| }, |
| |
| // ROM_CTRL |
| '{ |
| Mode: AppCShake, |
| Strength: sha3_pkg::L256, |
| PrefixMode: 1'b 1, // Use prefix parameter |
| Prefix: 'h 0 // TODO: Determine the prefix value |
| } |
| }; |
| |
| // MsgWidth : 64 |
| // MsgStrbW : 8 |
| parameter int unsigned AppDigestW = 256; |
| |
| typedef struct packed { |
| logic valid; |
| logic [MsgWidth-1:0] data; |
| logic [MsgStrbW-1:0] strb; |
| // last indicates the last beat of the data. strb can be partial only with |
| // last. |
| logic last; |
| } app_req_t; |
| |
| typedef struct packed { |
| logic ready; |
| logic done; |
| logic [AppDigestW-1:0] digest_share0; |
| logic [AppDigestW-1:0] digest_share1; |
| // Error is valid when done is high. If any error occurs during KDF, KMAC |
| // returns the garbage digest data with error. The KeyMgr discards the |
| // digest and may re-initiate the process. |
| logic error; |
| } app_rsp_t; |
| |
| parameter app_req_t APP_REQ_DEFAULT = '{ |
| valid: 1'b 0, |
| data: '0, |
| strb: '0, |
| last: 1'b 0 |
| }; |
| parameter app_rsp_t APP_RSP_DEFAULT = '{ |
| ready: 1'b1, |
| done: 1'b1, |
| digest_share0: AppDigestW'(32'hDEADBEEF), |
| digest_share1: AppDigestW'(32'hFACEBEEF), |
| error: 1'b1 |
| }; |
| |
| |
| //////////////////// |
| // Error Handling // |
| //////////////////// |
| |
| // Error structure is same to the SHA3 one. The codes do not overlap. |
| 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 |
| |
| // ErrKeyNotValid: KeyMgr interface raises an error if the secret key is |
| // not valid when KeyMgr initiates KDF. |
| ErrKeyNotValid = 8'h 01, |
| |
| // ErrSwPushMsgFifo: Sw writes data into Msg FIFO abruptly. |
| // This error occurs in below scenario: |
| // - Sw does not send "Start" command to KMAC then writes data into |
| // Msg FIFO |
| // - Sw writes data into Msg FIFO when KeyMgr is in operating |
| ErrSwPushedMsgFifo = 8'h 02, |
| |
| // ErrSwPushWrongCmd |
| // - Sw writes any command except CmdStart when Idle. |
| ErrSwPushedWrongCmd = 8'h 03, |
| |
| // ErrWaitTimerExpired |
| // Entropy Wait timer expired. Something wrong on EDN i/f |
| ErrWaitTimerExpired = 8'h 04, |
| |
| // ErrIncorrectEntropyMode |
| // Incorrect Entropy mode when entropy is ready |
| ErrIncorrectEntropyMode = 8'h 05 |
| } err_code_e; |
| |
| typedef struct packed { |
| logic valid; |
| err_code_e code; // Type of error |
| logic [23:0] info; // Additional Debug info |
| } err_t; |
| |
| /////////////////////// |
| // Library Functions // |
| /////////////////////// |
| |
| // Endian conversion functions (32-bit, 64-bit) |
| function automatic logic [31:0] conv_endian32( input logic [31:0] v, input logic swap); |
| logic [31:0] conv_data = {<<8{v}}; |
| conv_endian32 = (swap) ? conv_data : v ; |
| endfunction : conv_endian32 |
| |
| function automatic logic [63:0] conv_endian64( input logic [63:0] v, input logic swap); |
| logic [63:0] conv_data = {<<8{v}}; |
| conv_endian64 = (swap) ? conv_data : v ; |
| endfunction : conv_endian64 |
| |
| endpackage : kmac_pkg |