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 }