github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/caam/rtic.go (about)

     1  // NXP Cryptographic Acceleration and Assurance Module (CAAM) driver
     2  // https://github.com/usbarmory/tamago
     3  //
     4  // Copyright (c) WithSecure Corporation
     5  // https://foundry.withsecure.com
     6  //
     7  // Use of this source code is governed by the license
     8  // that can be found in the LICENSE file.
     9  
    10  package caam
    11  
    12  import (
    13  	"errors"
    14  	"fmt"
    15  
    16  	"github.com/usbarmory/tamago/bits"
    17  	"github.com/usbarmory/tamago/internal/reg"
    18  )
    19  
    20  // CAAM RTIC tuning
    21  var (
    22  	// RTICThrottle defines the clock cycles between RTIC hash operations
    23  	RTICThrottle uint32 = 0x000000ff
    24  	// RTICWatchdog defines the starting value for the RTIC Watchdog Timer
    25  	RTICWatchdog uint64 = 0x0000ffffffffffff
    26  )
    27  
    28  // CAAM RTIC registers
    29  const (
    30  	CAAM_RSTA = 0x6004
    31  	RSTA_CS   = 25
    32  	RSTA_AE   = 8
    33  	RSTA_MIS  = 4
    34  	RSTA_HE   = 3
    35  	RSTA_SV   = 2
    36  	RSTA_HD   = 1
    37  	RSTA_BSY  = 0
    38  
    39  	CAAM_RCMD = 0x600c
    40  	RCMD_RTC  = 2
    41  	RCMD_HO   = 1
    42  
    43  	CAAM_RCTL  = 0x6014
    44  	RCTL_RTME  = 8
    45  	RCTL_HOME  = 4
    46  	RCTL_RREQS = 1
    47  
    48  	CAAM_RTHR  = 0x601c
    49  	CAAM_RWDOG = 0x6028
    50  
    51  	// RTIC Memory Block Address
    52  	CAAM_RMaAb = 0x6100
    53  	// RTIC Memory Block Length
    54  	CAAM_RMaLb = 0x610c
    55  )
    56  
    57  // CAAM RTIC states
    58  const (
    59  	CS_IDLE = iota
    60  	CS_SINGLE
    61  	CS_RUN
    62  	CS_ERR
    63  )
    64  
    65  // MemoryBlock represents a memory region for RTIC monitoring.
    66  type MemoryBlock struct {
    67  	Address uint32
    68  	Length  uint32
    69  }
    70  
    71  // RSTA returns the Run Time Integrity Checker (RTIC) Status.
    72  func (hw *CAAM) RSTA() (cs uint32, err error) {
    73  	rsta := reg.Read(hw.Base + CAAM_RSTA)
    74  
    75  	switch {
    76  	case bits.Get(&rsta, RSTA_AE, 0xf) != 0:
    77  		err = errors.New("illegal address")
    78  	case bits.Get(&rsta, RSTA_MIS, 0xf) != 0:
    79  		err = errors.New("memory block corruption")
    80  	case bits.Get(&rsta, RSTA_HE, 1) != 0:
    81  		err = errors.New("hashing error")
    82  	case bits.Get(&rsta, RSTA_SV, 1) != 0:
    83  		err = errors.New("security violation")
    84  	case bits.Get(&rsta, RSTA_BSY, 1) != 0:
    85  		err = errors.New("RTIC busy")
    86  	}
    87  
    88  	cs = bits.Get(&rsta, RSTA_CS, 0b11)
    89  
    90  	return
    91  }
    92  
    93  func (hw *CAAM) initRTIC(blocks []MemoryBlock) error {
    94  	if len(blocks) == 0 || len(blocks) > 4 {
    95  		return errors.New("invalid memory block count")
    96  	}
    97  
    98  	for i, b := range blocks {
    99  		reg.Write(hw.Base+CAAM_RMaAb+uint32(i)*0x20+0x4, b.Address)
   100  		reg.Write(hw.Base+CAAM_RMaLb+uint32(i)*0x20, b.Length)
   101  	}
   102  
   103  	return nil
   104  }
   105  
   106  // EnableRTIC enables the CAAM Run Time Integrity Checker (RTIC) for up to 4
   107  // memory blocks.
   108  //
   109  // Once enabled, the RTIC performs periodic (see RTICThrottle) hardware backed
   110  // SHA256 hashing and raising a security violation (see RSTA()) in case of
   111  // mismatch with the first computed hash.
   112  //
   113  // Any security violation (which also affects the SNVS SSM) or memory block
   114  // reconfiguration require a hardware reset.
   115  func (hw *CAAM) EnableRTIC(blocks []MemoryBlock) (err error) {
   116  	hw.Lock()
   117  	defer hw.Unlock()
   118  
   119  	if hw.Base == 0 || hw.CCGR == 0 {
   120  		return errors.New("invalid CAAM instance")
   121  	}
   122  
   123  	if err = hw.initRTIC(blocks); err != nil {
   124  		return
   125  	}
   126  
   127  	if cs, err := hw.RSTA(); err != nil || cs != CS_IDLE {
   128  		return fmt.Errorf("invalid state (cs:%d, err:%v)", cs, err)
   129  	}
   130  
   131  	// hash maximum number of blocks at each iteration
   132  	reg.SetN(hw.Base+CAAM_RCTL, RCTL_RREQS, 0b111, 0b111)
   133  
   134  	// apply run-time tuning settings
   135  	reg.Write(hw.Base+CAAM_RTHR, RTICThrottle)
   136  	reg.Write(hw.Base+CAAM_RWDOG, uint32(RTICWatchdog>>32))
   137  	reg.Write(hw.Base+CAAM_RWDOG+0x4, uint32(RTICWatchdog))
   138  
   139  	// set memory blocks for hash once and run-time check operations
   140  	for i := 0; i < len(blocks); i++ {
   141  		reg.Set(hw.Base+CAAM_RCTL, RCTL_HOME+i)
   142  		reg.Set(hw.Base+CAAM_RCTL, RCTL_RTME+i)
   143  	}
   144  
   145  	// generate reference hash value and start run-time verification
   146  	reg.SetN(hw.Base+CAAM_RCMD, RCMD_HO, 0b11, 0b11)
   147  
   148  	return
   149  }