|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | { | 
|  | name:               "hmac", | 
|  | human_name:         "HMAC Accelerator", | 
|  | one_line_desc:      "Accelerator for SHA-256-based keyed hash message authentication code and the SHA-256 hash function", | 
|  | one_paragraph_desc: ''' | 
|  | HMAC Accelerator is a keyed hash based message authentication code generator using [SHA-256][nist-fips-180-4] to check the integrity of an incoming message and optionally a signature signed with the same secret key. | 
|  | This HMAC implementation is not hardened against side-channel analysis (SCA) or fault injection (FI) attacks; it is meant purely for hashing acceleration. | 
|  | If hardened MAC operations are required, either KMAC Accelerator or a software implementation should be used. | 
|  |  | 
|  | [nist-fips-180-4]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf | 
|  | ''' | 
|  | design_spec:        "../doc", | 
|  | dv_doc:             "../doc/dv", | 
|  | hw_checklist:       "../doc/checklist", | 
|  | sw_checklist:       "/sw/device/lib/dif/dif_hmac", | 
|  | revisions: [ | 
|  | { | 
|  | version:            "0.5", | 
|  | life_stage:         "L2", | 
|  | design_stage:       "D3", | 
|  | verification_stage: "V3", | 
|  | commit_id:          "635afdb8dedbb50c235bd772b36002925c499884", | 
|  | notes:              "" | 
|  | } | 
|  | { | 
|  | version:            "1.0", | 
|  | life_stage:         "L1", | 
|  | design_stage:       "D3", | 
|  | verification_stage: "V2", | 
|  | dif_stage:          "S2", | 
|  | notes:              "", | 
|  | } | 
|  | ] | 
|  | clocking: [{clock: "clk_i", reset: "rst_ni", idle: "idle_o"}], | 
|  | bus_interfaces: [ | 
|  | { protocol: "tlul", direction: "device" } | 
|  | ], | 
|  | interrupt_list: [ | 
|  | { name: "hmac_done", | 
|  | desc: "HMAC-256 completes a message with key" | 
|  | } | 
|  | { name: "fifo_empty", | 
|  | desc: "Message FIFO empty condition" | 
|  | } | 
|  | { name: "hmac_err", | 
|  | desc: "HMAC error occurred. ERR_CODE register shows which error occurred" | 
|  | } | 
|  | ], | 
|  | alert_list: [ | 
|  | { name: "fatal_fault", | 
|  | desc: ''' | 
|  | This fatal alert is triggered when a fatal TL-UL bus integrity fault is detected. | 
|  | ''' | 
|  | } | 
|  | ], | 
|  | inter_signal_list: [ | 
|  | { name:    "idle", | 
|  | type:    "uni", | 
|  | act:     "req", | 
|  | package: "prim_mubi_pkg", | 
|  | struct:  "mubi4", | 
|  | width:   "1" | 
|  | } | 
|  | ], | 
|  | param_list: [ | 
|  | { name:    "NumWords", | 
|  | type:    "int", | 
|  | default: "8", | 
|  | desc:    "Number of words for digest/ key", | 
|  | local:   "true" | 
|  | } | 
|  | ], | 
|  | countermeasures: [ | 
|  | { name: "BUS.INTEGRITY", | 
|  | desc: "End-to-end bus integrity scheme." | 
|  | } | 
|  | ] | 
|  | regwidth: "32", | 
|  | registers: [ | 
|  | { name: "CFG", | 
|  | desc: '''HMAC Configuration register. | 
|  |  | 
|  | The register is updated when the engine is in Idle. | 
|  | If the software updates the register while the engine computes the hash, | 
|  | the updated value is discarded. | 
|  | ''', | 
|  | hwext:    "true", | 
|  | hwqe:     "true", | 
|  | swaccess: "rw", | 
|  | hwaccess: "hrw", | 
|  | fields: [ | 
|  | { bits: "0", | 
|  | name: "hmac_en", | 
|  | desc: '''HMAC datapath enable. | 
|  |  | 
|  | If this bit is 1, HMAC operates when `hash_start` toggles. | 
|  | ''', | 
|  | tags: [// don't enable hmac and sha data paths - we will do that in functional tests | 
|  | "excl:CsrNonInitTests:CsrExclWrite"] | 
|  | } | 
|  | { bits: "1", | 
|  | name: "sha_en", | 
|  | desc: '''SHA256 enable. If 0, SHA engine won't initiate compression, | 
|  | this is used to stop operation of the SHA engine until configuration | 
|  | has been done. When the SHA engine is disabled the digest is cleared.''' | 
|  | tags: [// don't enable hmac and sha data paths - we will do that in functional tests | 
|  | "excl:CsrNonInitTests:CsrExclWrite"] | 
|  | } | 
|  | { bits: "2", | 
|  | name: "endian_swap", | 
|  | desc: '''Endian swap. | 
|  |  | 
|  | If 0, each value will be added to the message in little-endian | 
|  | byte order. The value is written to MSG_FIFO same to the SW writes. | 
|  |  | 
|  | If 1, then each individual multi-byte value, regardless of its | 
|  | alignment, written to !!MSG_FIFO will be added to the message | 
|  | in big-endian byte order. | 
|  |  | 
|  | A message written to !!MSG_FIFO one byte at a time will not be | 
|  | affected by this setting. | 
|  |  | 
|  | From a hardware perspective byte swaps are performed on a TL-UL | 
|  | word granularity. | 
|  | ''', | 
|  | resval: "0", | 
|  | } | 
|  | { bits: "3", | 
|  | name: "digest_swap", | 
|  | desc: '''Digest register byte swap. | 
|  |  | 
|  | If 1 the value contained in each digest output register is | 
|  | converted to big-endian byte order. | 
|  | This setting does not affect the order of the digest output | 
|  | registers, !!DIGEST_0 still contains the first 4 bytes of | 
|  | the digest. | 
|  | ''', | 
|  | resval: "0", | 
|  | } | 
|  | ] | 
|  | } | 
|  | { name: "CMD", | 
|  | desc: "HMAC command register", | 
|  | swaccess: "r0w1c", | 
|  | hwaccess: "hro", | 
|  | hwext: "true", | 
|  | hwqe:  "true", | 
|  | tags: [// design assertion : after hash_start sets, can only wr msg or set hash_process | 
|  | // design assertion : hash_process can be set only after hash_start is set | 
|  | "excl:CsrAllTests:CsrExclWrite"] | 
|  | fields: [ | 
|  | { bits: "0", | 
|  | name: "hash_start", | 
|  | desc: '''If writes 1 into this field, SHA256 or HMAC begins its operation. | 
|  |  | 
|  | CPU should configure relative information first, such as message_length, | 
|  | secret_key. | 
|  | ''', | 
|  | } | 
|  | { bits: "1", | 
|  | name: "hash_process", | 
|  | desc: '''If writes 1 into this field, SHA256 or HMAC calculates the digest or signing | 
|  | based on currently received message. | 
|  | ''' | 
|  | } | 
|  | ], | 
|  | } | 
|  | { name: "STATUS", | 
|  | desc: "HMAC Status register", | 
|  | swaccess: "ro", | 
|  | hwaccess: "hwo", | 
|  | hwext: "true", | 
|  | fields: [ | 
|  | { bits: "0", | 
|  | name: "fifo_empty", | 
|  | desc: "FIFO empty", | 
|  | resval: "1" | 
|  | } | 
|  | { bits: "1", | 
|  | name: "fifo_full", | 
|  | desc: "FIFO full. Data written to the FIFO whilst it is full will cause back-pressure on the interconnect" | 
|  | } | 
|  | { bits: "8:4", | 
|  | name: "fifo_depth", | 
|  | desc: "FIFO entry count." | 
|  | } | 
|  | ] | 
|  | } | 
|  | { name: "ERR_CODE", | 
|  | desc: "HMAC Error Code", | 
|  | swaccess: "ro", | 
|  | hwaccess: "hwo", | 
|  | fields: [ | 
|  | { bits: "31:0", | 
|  | name: "err_code", | 
|  | desc: '''If error interrupt occurs, this register has information of error cause. | 
|  | Please take a look at `hw/ip/hmac/rtl/hmac_pkg.sv:err_code_e enum type. | 
|  | ''' | 
|  | tags: [// Randomly write mem will cause this reg updated by design | 
|  | "excl:CsrNonInitTests:CsrExclCheck"] | 
|  | } | 
|  | ] | 
|  | } | 
|  | { name: "WIPE_SECRET", | 
|  | desc: '''Randomize internal secret registers. | 
|  |  | 
|  | If CPU writes value into the register, the value is used to randomize internal | 
|  | variables such as secret key, internal state machine, or hash value. | 
|  | ''', | 
|  | swaccess: "wo", | 
|  | hwaccess: "hro", | 
|  | hwext: "true", | 
|  | hwqe: "true", | 
|  | fields: [ | 
|  | { bits: "31:0", name:"secret", desc: "Secret value" } | 
|  | ] | 
|  | } | 
|  | { multireg: { | 
|  | name: "KEY", | 
|  | desc: '''HMAC Secret Key | 
|  |  | 
|  | SHA256 assumes secret key is hashed 256bit key. | 
|  | Order of the secret key is: | 
|  | key[255:0] = {KEY0, KEY1, KEY2, ... , KEY7}; | 
|  |  | 
|  | The registers are allowed to be updated when the engine is in Idle state. | 
|  | If the engine computes the hash, it discards any attempts to update the secret keys | 
|  | and report an error. | 
|  | ''', | 
|  | count: "NumWords", | 
|  | cname: "HMAC", | 
|  | hwext: "true", | 
|  | hwqe : "true", | 
|  | swaccess: "wo", | 
|  | hwaccess: "hrw", | 
|  | fields: [ | 
|  | { bits: "31:0", name: "key", desc: "32-bit chunk of 256-bit Secret Key" } | 
|  | ], | 
|  | } | 
|  | } | 
|  | { multireg: { | 
|  | name: "DIGEST", | 
|  | desc: '''Digest output. If HMAC is disabled, the register shows result of SHA256 | 
|  |  | 
|  | Order of the digest is: | 
|  | digest[255:0] = {DIGEST0, DIGEST1, DIGEST2, ... , DIGEST7}; | 
|  | ''', | 
|  | count: "NumWords", | 
|  | cname: "HMAC", | 
|  | swaccess: "ro", | 
|  | hwaccess: "hwo", | 
|  | hwext: "true", | 
|  | fields: [ | 
|  | { bits: "31:0", name: "digest", desc: "32-bit chunk of 256-bit Digest" } | 
|  | ] | 
|  | } | 
|  | } | 
|  | { name: "MSG_LENGTH_LOWER", | 
|  | desc: '''Received Message Length calculated by the HMAC in bits [31:0] | 
|  |  | 
|  | Message is byte granularity. | 
|  | lower 3bits [2:0] are ignored.''', | 
|  | swaccess: "ro", | 
|  | hwaccess: "hwo", | 
|  | fields: [ | 
|  | { bits: "31:0", name: "v", desc: "Message Length [31:0]" } | 
|  | ] | 
|  | } | 
|  | { name: "MSG_LENGTH_UPPER", | 
|  | desc: "Received Message Length calculated by the HMAC in bits [63:32]", | 
|  | swaccess: "ro", | 
|  | hwaccess: "hwo", | 
|  | fields: [ | 
|  | { bits: "31:0", name: "v", desc: "Message Length [63:32]" } | 
|  | ] | 
|  | } | 
|  | { skipto: "0x800" } | 
|  | { window: { | 
|  | name: "MSG_FIFO" | 
|  | items: "512"      // 2kB | 
|  | swaccess: "wo", | 
|  | byte-write: "true", | 
|  | desc: '''Message FIFO. Any write to this window will be appended to the FIFO. Only the lower [1:0] bits of the address matter to writes within the window (for correctly dealing with non 32-bit writes) | 
|  | ''' | 
|  | } | 
|  | } | 
|  | ], | 
|  | } |