blob: fe2b1874e900608b3c56d770b55a6a73faff45a0 [file] [log] [blame]
// 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)
'''
}
}
],
}