github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/snvs/snvs.go (about) 1 // NXP Secure Non-Volatile Storage (SNVS) support 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 snvs implements a driver for NXP Secure Non-Volatile Storage (SNVS) 11 // following reference specifications: 12 // - IMX6ULLRM - i.MX 6ULL Applications Processor Reference Manual - Rev 1 2017/11 13 // - IMX6ULLSRM - i.MX 6ULL Applications Processor Security Reference Manual - Rev 0 2016/09 14 // 15 // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as 16 // supported by the TamaGo framework for bare metal Go on ARM SoCs, see 17 // https://github.com/usbarmory/tamago. 18 package snvs 19 20 import ( 21 "github.com/usbarmory/tamago/bits" 22 "github.com/usbarmory/tamago/internal/reg" 23 24 "sync" 25 "time" 26 ) 27 28 // SNVS registers 29 const ( 30 SNVS_HPCOMR = 0x04 31 HPCOMR_HAC_STOP = 19 32 HPCOMR_HAC_LOAD = 17 33 HPCOMR_HAC_EN = 16 34 35 SNVS_HPSVCR = 0x10 36 HPSVCR_LPSV_CFG = 30 37 38 SNVS_HPSR = 0x14 39 HPSR_OTPMK_ZERO = 27 40 HPSR_OTPMK_SYNDROME = 16 41 42 SNVS_HPHACIVR = 0x1c 43 SNVS_HPHACR = 0x20 44 45 HPSR_SSM_STATE = 8 46 47 SNVS_LPTDCR = 0x48 48 LPTDCR_VT_EN = 6 49 LPTDCR_TT_EN = 5 50 LPTDCR_CT_EN = 4 51 52 SNVS_LPSR = 0x4c 53 LPSR_VTD = 6 54 LPSR_TTD = 5 55 LPSR_CTD = 4 56 LPSR_PGD = 3 57 58 SNVS_LPPGDR = 0x64 59 // Power Glitch Detector Register hardwired value 60 LPPGDR_PGD_VAL = 0x41736166 61 ) 62 63 // System Security Monitor (SSM) states 64 const ( 65 SSM_STATE_INIT = 0b0000 66 SSM_STATE_HARD_FAIL = 0b0001 67 SSM_STATE_SOFT_FAIL = 0b0011 68 SSM_STATE_CHECK = 0b1001 69 SSM_STATE_NONSECURE = 0b1011 70 SSM_STATE_TRUSTED = 0b1101 71 SSM_STATE_SECURE = 0b1111 72 ) 73 74 // DryIce registers 75 const ( 76 DRYICE_DTOCR = 0x00 77 DTOCR_DRYICE_EN = 0 78 79 DRYICE_DTMR = 0x04 80 DTMR_TEMP_MON_TRIM = 22 81 DTMR_VOLT_MON_TRIM = 12 82 DTMR_BGR_TRIM = 6 83 DTMR_PROG_TRIM = 0 84 85 DRYICE_DTRR = 0x08 86 DTRR_SNVS_CLK_TAMP_DETECT = 2 87 DTRR_DRYICE_TEMP_DETECT = 1 88 DTRR_DRYICE_VOLT_TAMP_DETECT = 0 89 90 DRYICE_DMCR = 0x0c 91 DMCR_CLOCK_DET_EN = 2 92 DMCR_VOLT_DET_EN = 1 93 DMCR_TEMP_DET_EN = 0 94 ) 95 96 // SNVS represents the SNVS instance. 97 type SNVS struct { 98 sync.Mutex 99 100 // Base register 101 Base uint32 102 // Clock gate register 103 CCGR uint32 104 // Clock gate 105 CG int 106 // auxiliary logic base register 107 DryIce uint32 108 109 // control registers 110 hpcomr uint32 111 hpsvcr uint32 112 hpsr uint32 113 hphacivr uint32 114 hphacr uint32 115 lptdcr uint32 116 lpsr uint32 117 lppgdr uint32 118 119 // DryIce registers 120 dtocr uint32 121 dtmr uint32 122 dtrr uint32 123 dmcr uint32 124 125 // active configuration 126 sp SecurityPolicy 127 } 128 129 // SecurityPolicy represents an SNVS configuration and is used to configure 130 // tamper detection or return detected violations (see SetPolicy()). 131 type SecurityPolicy struct { 132 // SRTC Clock Tampering 133 Clock bool 134 // Temperature Tamper 135 Temperature bool 136 // Voltage Tamper 137 Voltage bool 138 // Power Glitch Violation (used only when reporting, see Monitor()) 139 Power bool 140 141 // SecurityViolation controls whether monitored conditions generate a 142 // violation which transitions the SNVS state to soft fail, preventing 143 // access to the OTPMK and SNVS availability (see Available()). 144 SecurityViolation bool 145 146 // HardFail controls whether a soft fail state (see SecurityViolation) 147 // transitions the system to a hard reset after a predefined system 148 // clock delay (see HAC). 149 HardFail bool 150 151 // HAC is used to stop and reset the initial value of the High 152 // Assurance Counter, a delay in system clocks between a soft fail and 153 // a hard fail, or return the current HAC value. 154 HAC uint32 155 156 // State represents the System Security Monitor (SSM) State (used only 157 // when reporting, see Monitor()). 158 State uint8 159 } 160 161 func (hw *SNVS) initDryIce(calibrationData uint32) { 162 hw.dtocr = hw.DryIce + DRYICE_DTOCR 163 hw.dtmr = hw.DryIce + DRYICE_DTMR 164 hw.dtrr = hw.DryIce + DRYICE_DTRR 165 hw.dmcr = hw.DryIce + DRYICE_DMCR 166 167 reg.SetN(hw.dtmr, DTMR_TEMP_MON_TRIM, 0x3ff, bits.Get(&calibrationData, 0, 0x3ff)) 168 reg.SetN(hw.dtmr, DTMR_VOLT_MON_TRIM, 0x3ff, bits.Get(&calibrationData, 10, 0x3ff)) 169 reg.SetN(hw.dtmr, DTMR_BGR_TRIM, 0x3f, bits.Get(&calibrationData, 20, 0x3f)) 170 reg.SetN(hw.dtmr, DTMR_PROG_TRIM, 0x3f, bits.Get(&calibrationData, 26, 0x3f)) 171 } 172 173 // Init initializes the SNVS controller, the calibration data is fused 174 // individually for each part and is required for correct initialization of the 175 // DryIce auxiliary logic (when available). 176 func (hw *SNVS) Init(calibrationData uint32) { 177 if hw.Base == 0 || hw.CCGR == 0 { 178 panic("invalid SNVS instance") 179 } 180 181 // enable clock 182 reg.SetN(hw.CCGR, hw.CG, 0b11, 0b11) 183 184 hw.hpcomr = hw.Base + SNVS_HPCOMR 185 hw.hpsvcr = hw.Base + SNVS_HPSVCR 186 hw.hpsr = hw.Base + SNVS_HPSR 187 hw.hphacivr = hw.Base + SNVS_HPHACIVR 188 hw.hphacr = hw.Base + SNVS_HPHACR 189 hw.lptdcr = hw.Base + SNVS_LPTDCR 190 hw.lpsr = hw.Base + SNVS_LPSR 191 hw.lppgdr = hw.Base + SNVS_LPPGDR 192 193 if hw.DryIce > 0 { 194 hw.initDryIce(calibrationData) 195 } 196 } 197 198 func (hw *SNVS) setDryIcePolicy(sp SecurityPolicy) { 199 reg.Set(hw.dtocr, DTOCR_DRYICE_EN) 200 time.Sleep(1 * time.Millisecond) 201 202 reg.SetTo(hw.dmcr, DMCR_VOLT_DET_EN, sp.Voltage) 203 reg.SetTo(hw.dmcr, DMCR_TEMP_DET_EN, sp.Temperature) 204 reg.SetTo(hw.dmcr, DMCR_CLOCK_DET_EN, sp.Clock) 205 time.Sleep(1 * time.Millisecond) 206 207 // clear records 208 reg.Set(hw.dtrr, DTRR_DRYICE_TEMP_DETECT) 209 reg.Set(hw.dtrr, DTRR_DRYICE_VOLT_TAMP_DETECT) 210 reg.Set(hw.dtrr, DTRR_SNVS_CLK_TAMP_DETECT) 211 } 212 213 // SetPolicy configures the SNVS tamper detection and security violation 214 // policy, It can be used to prevent a transition from soft fail to hard fail 215 // if invoked within the expiration of a previously applied policy (see 216 // SecurityPolicy.HAC). 217 func (hw *SNVS) SetPolicy(sp SecurityPolicy) { 218 hw.Lock() 219 defer hw.Unlock() 220 221 // stop High Assurance Counter 222 reg.Set(hw.hpcomr, HPCOMR_HAC_STOP) 223 reg.Clear(hw.hpcomr, HPCOMR_HAC_EN) 224 225 // set Power Glitch Detector value and clear its record 226 reg.Write(hw.lppgdr, LPPGDR_PGD_VAL) 227 reg.Set(hw.lpsr, LPSR_PGD) 228 229 // set LP security violation configuration 230 reg.SetTo(hw.hpsvcr, HPSVCR_LPSV_CFG+1, sp.SecurityViolation) 231 232 if sp.HardFail { 233 reg.Clear(hw.hpcomr, HPCOMR_HAC_STOP) 234 reg.Write(hw.hphacivr, sp.HAC) 235 reg.Set(hw.hpcomr, HPCOMR_HAC_LOAD) 236 reg.Set(hw.hpcomr, HPCOMR_HAC_EN) 237 } 238 239 if hw.DryIce > 0 { 240 hw.setDryIcePolicy(sp) 241 } 242 243 // set tamper monitors 244 reg.SetTo(hw.lptdcr, LPTDCR_VT_EN, sp.Voltage) 245 reg.SetTo(hw.lptdcr, LPTDCR_TT_EN, sp.Temperature) 246 reg.SetTo(hw.lptdcr, LPTDCR_CT_EN, sp.Clock) 247 248 // clear records 249 reg.Set(hw.lpsr, LPSR_VTD) 250 reg.Set(hw.lpsr, LPSR_TTD) 251 reg.Set(hw.lpsr, LPSR_CTD) 252 253 hw.sp = sp 254 } 255 256 // Monitor returns the SNVS tamper System Security Monitor (SSM) state, its 257 // configured violation policy and the current High Assurance Counter value. 258 func (hw *SNVS) Monitor() (violations SecurityPolicy) { 259 clk := reg.IsSet(hw.lpsr, LPSR_CTD) 260 tmp := reg.IsSet(hw.lpsr, LPSR_TTD) 261 vcc := reg.IsSet(hw.lpsr, LPSR_VTD) 262 263 if hw.DryIce > 0 { 264 clk = clk || reg.IsSet(hw.dtrr, DTRR_SNVS_CLK_TAMP_DETECT) 265 tmp = tmp || reg.IsSet(hw.dtrr, DTRR_DRYICE_VOLT_TAMP_DETECT) 266 vcc = vcc || reg.IsSet(hw.dtrr, DTRR_DRYICE_TEMP_DETECT) 267 } 268 269 return SecurityPolicy{ 270 Clock: clk, 271 Temperature: tmp, 272 Voltage: vcc, 273 Power: reg.IsSet(hw.lpsr, LPSR_PGD), 274 SecurityViolation: hw.sp.SecurityViolation, 275 HardFail: hw.sp.HardFail, 276 HAC: reg.Read(hw.hphacr), 277 State: uint8(reg.Get(hw.hpsr, HPSR_SSM_STATE, 0b1111)), 278 } 279 } 280 281 // Available verifies whether the Secure Non Volatile Storage (SNVS) is 282 // correctly programmed and in Trusted or Secure state (indicating that Secure 283 // Boot is enabled and no security violations have been detected). 284 // 285 // The unique OTPMK internal key is available only when Secure Boot (HAB) is 286 // enabled, otherwise a Non-volatile Test Key (NVTK), identical for each SoC, 287 // is used. 288 func (hw *SNVS) Available() bool { 289 hpsr := reg.Read(hw.hpsr) 290 291 // ensure that the OTPMK has been correctly programmed 292 if bits.Get(&hpsr, HPSR_OTPMK_ZERO, 1) != 0 || bits.Get(&hpsr, HPSR_OTPMK_SYNDROME, 0x1ff) != 0 { 293 return false 294 } 295 296 switch bits.Get(&hpsr, HPSR_SSM_STATE, 0b1111) { 297 case SSM_STATE_TRUSTED, SSM_STATE_SECURE: 298 return true 299 default: 300 return false 301 } 302 }