NIST defines Root of trust (RoT) as follows

Roots of trust are highly reliable hardware, firmware, and software components that perform specific, critical security functions. Because roots of trust are inherently trusted, they must be secure by design.

Basically, It’s hardware implementation of security functions like

  • key management(generation and storage)
  • cryptographic functions(Block ciphers, Asymmetric key crypto, Hash)

The hardware is designed with security threat model in mind. NIST Guidelines on Hardware Rooted Security in Mobile Devices states 3 important guidelines for RoT

  • Device Integrity: Device integrity is the absence of corruption in the hardware, firmware and software of a device. A mobile device can provide evidence that it has maintained device integrity if its software, firmware, and hardware configurations can be shown to be in a state that is trusted by a relying party
  • Isolation: Isolation prevents unintended interaction between applications and Information Contexts on the same device.
  • Protected Storage: Protected storage preserves the confidentiality and integrity of data on the device while at rest, while in use (in the event an unauthorized application attempts to access an item in protected storage), and upon revocation of access.

If you want to find examples of hardware implementation guidelines, a list can be found on opentitan. For example, There are guidelines for avoiding side-channel leakage

Recommendation 2: Side-channel leakage considerations Consider side-channel leakage of any secret information (side channels include timing, power, EM radiation, caches, and micro-architectural state, among others)

Process secret information in at least a 32-bit wide datapath Use fixed/constant time operations when handling secrets (see 6 and [11]) Don’t branch/perform conditional operations based on secret values

Naturally, threat model needs to be defined, again opentitan threat model

Example 1 Link to heading

One interesting guideline from opentitan is Alerts

Recommendation 5: Alerts Generate alerts on any detected anomaly (need to define what priority/severity should be assigned) Where possible, prefer to take a local action (clearing/randomizing state, cease processing) in addition to generating the alert

This is quick example from opentitan of an alert.

Starting in hw/ip/aes/rtl/aes_ctr_fsm.sv

      CTR_ERROR: begin
        // SEC_CM: CTR.FSM.LOCAL_ESC
        // Terminal error state
        alert_o = 1'b1;
      end

      // We should never get here. If we do (e.g. via a malicious
      // glitch), error out immediately.
      default: begin
        aes_ctr_ns = CTR_ERROR;
        alert_o = 1'b1;
      end

eventually alert_o get connected to ctrl_alert and to alert_fatal_o. And status is set in the CSR alert_fatal_fault

  // Collect fatal alert signals.
  assign alert_fatal_o = ctrl_err_storage |
                         ctr_alert        |
                         cipher_alert     |
                         ctrl_alert       |
                         intg_err_alert_i;

  // Make the fatal alert observable via status register.
  assign hw2reg.status.alert_fatal_fault.d  = alert_fatal_o;
  assign hw2reg.status.alert_fatal_fault.de = alert_fatal_o;

Example 2 Link to heading

Another example is Recommendation 3: Fault injection countermeasures

Use parity/ECC on memories and data paths (note here that ECC is not true integrity, have to use hash to prevent forgery, see 1). For memories, ECC is helpful to protect instruction streams or values that can cause “branching control flows” that redirect execution flow. Parity is potentially helpful if detection of corruption is adequate (though double-glitch fault injection can fool parity, so Hsiao or other detect-2-error codes can be used, even without correction circuitry implemented). When committing to an irrevocable action (e.g. burning into OTP, unlocking part of the device/increasing permissions), ECC is probably more appropriate.

For example, Flash controller hw/ip/flash_ctrl/rtl/flash_phy_rd.sv is using hamming ECC(Error correcting code)


  prim_secded_hamming_76_68_dec u_dec (
    .data_i(data_i),
    .data_o(data_ecc_chk),
    .syndrome_o(),
    .err_o({ecc_multi_err, ecc_single_err})
  );

  // send out error indication when ecc is enabled
  assign data_err = valid_ecc & ecc_multi_err;

  // reliability ECC errors cause both in-band and out-of-band errors
  assign relbl_ecc_err_o = data_err;

  // If there is a detected multi-bit error or a single bit error, always return the
  // ECC corrected result (even though it is possibly wrong).
  // There is no data error of any kind (specifically when multi_err is disabled), just
  // return the raw data so that it can be debugged.
  assign data_int = data_err | ecc_single_err_o ?
                    data_ecc_chk :
                    data_i[PlainDataWidth-1:0];