| // 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) |
| ''' |
| } |
| } |
| ], |
| } |