github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/bee/bee.go (about) 1 // NXP Bus Encryption Engine (BEE) 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 bee implements a driver for the NXP Bus Encryption Engine (BEE) 11 // adopting the following reference specifications: 12 // - IMX6ULSRM - i.MX6UL Security Reference Manual - Rev 0 04/2016 13 // 14 // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as 15 // supported by the TamaGo framework for bare metal Go on ARM SoCs, see 16 // https://github.com/usbarmory/tamago. 17 package bee 18 19 import ( 20 "crypto/aes" 21 "crypto/rand" 22 "errors" 23 "fmt" 24 "sync" 25 26 "github.com/usbarmory/tamago/dma" 27 "github.com/usbarmory/tamago/internal/reg" 28 "github.com/usbarmory/tamago/soc/nxp/snvs" 29 ) 30 31 // BEE registers 32 const ( 33 BEE_CTRL = 0x00 34 CTRL_CLK_EN_LOCK = 31 35 CTRL_SFTRST_N_LOCK = 30 36 CTRL_AES_MODE_LOCK = 29 37 CTRL_SECURITY_LEVEL_LOCK = 24 38 CTRL_AES_KEY_SEL_LOCK = 20 39 CTRL_BEE_ENABLE_LOCK = 16 40 CTRL_CLK_EN = 15 41 CTRL_SFTRST_N = 14 42 CTRL_AES_MODE = 13 43 CTRL_SECURITY_LEVEL = 8 44 CTRL_AES_KEY_SEL = 4 45 CTRL_BEE_ENABLE = 0 46 47 BEE_ADDR_OFFSET0 = 0x04 48 BEE_ADDR_OFFSET1 = 0x08 49 50 // AES key 51 BEE_AES_KEY0_W0 = 0x0c 52 BEE_AES_KEY0_W1 = 0x10 53 BEE_AES_KEY0_W2 = 0x14 54 BEE_AES_KEY0_W3 = 0x18 55 56 // AES CTR nonce 57 BEE_AES_KEY1_W0 = 0x20 58 BEE_AES_KEY1_W1 = 0x24 59 BEE_AES_KEY1_W2 = 0x28 60 BEE_AES_KEY1_W3 = 0x2c 61 ) 62 63 const ( 64 AliasRegion0 = 0x10000000 65 AliasRegion1 = 0x30000000 66 AliasRegionSize = 0x20000000 67 ) 68 69 // BEE represents the Bus Encryption Engine instance. 70 type BEE struct { 71 mu sync.Mutex 72 73 // Base register 74 Base uint32 75 // SNVS instance 76 SNVS *snvs.SNVS 77 78 // control registers 79 ctrl uint32 80 addr0 uint32 81 addr1 uint32 82 83 // AES key pointer 84 key uint32 85 // AES CTR nonce pointer 86 nonce uint32 87 } 88 89 // Init initializes the BEE module. 90 func (hw *BEE) Init() { 91 hw.mu.Lock() 92 defer hw.mu.Unlock() 93 94 if hw.Base == 0 { 95 panic("invalid BEE instance") 96 } 97 98 hw.ctrl = hw.Base + BEE_CTRL 99 hw.addr0 = hw.Base + BEE_ADDR_OFFSET0 100 hw.addr1 = hw.Base + BEE_ADDR_OFFSET1 101 hw.key = hw.Base + BEE_AES_KEY0_W0 102 hw.nonce = hw.Base + BEE_AES_KEY1_W0 103 104 // enable clock 105 reg.Set(hw.ctrl, CTRL_CLK_EN) 106 // disable reset 107 reg.Set(hw.ctrl, CTRL_SFTRST_N) 108 109 // disable 110 reg.Clear(hw.ctrl, CTRL_BEE_ENABLE) 111 } 112 113 func (hw *BEE) generateKey(ptr uint32) (err error) { 114 // avoid key exposure to external RAM 115 key, err := dma.NewRegion(uint(ptr), aes.BlockSize, false) 116 117 if err != nil { 118 return 119 } 120 121 addr, buf := key.Reserve(aes.BlockSize, 0) 122 123 if n, err := rand.Read(buf); n != aes.BlockSize || err != nil { 124 return errors.New("could not set random key") 125 } 126 127 if addr != uint(ptr) { 128 return errors.New("invalid key address") 129 } 130 131 return 132 } 133 134 func checkRegion(region uint32, offset uint32) error { 135 if region&0xffff != 0 { 136 return errors.New("address must be 64KB aligned") 137 } 138 139 if offset >= AliasRegion0 && offset < AliasRegion0+AliasRegionSize || 140 offset >= AliasRegion1 && offset < AliasRegion1+AliasRegionSize { 141 return errors.New("invalid region (offset overalps with aliased region)") 142 } 143 144 return nil 145 } 146 147 // Enable activates the BEE using the argument memory regions, each can be up 148 // to AliasRegionSize (512 MB) in size. 149 // 150 // After activation the regions are encrypted using AES CTR. On secure booted 151 // systems the internal OTPMK is used as key, otherwise a random one is 152 // generated and assigned. 153 // 154 // After enabling, both regions should only be accessed through their 155 // respective aliased spaces (see AliasRegion0 and AliasRegion1) and only with 156 // caching enabled (see arm.ConfigureMMU). 157 func (hw *BEE) Enable(region0 uint32, region1 uint32) (err error) { 158 hw.mu.Lock() 159 defer hw.mu.Unlock() 160 161 if err = checkRegion(region0, region0-AliasRegion0); err != nil { 162 return fmt.Errorf("region0 error: %v", err) 163 } 164 165 if err = checkRegion(region1, region1-AliasRegion1); err != nil { 166 return fmt.Errorf("region1 error: %v", err) 167 } 168 169 if hw.addr0 == 0 { 170 return errors.New("invalid BEE instance") 171 } 172 173 reg.Write(hw.addr0, region0>>16) 174 reg.Write(hw.addr1, region1>>16) 175 176 if hw.SNVS != nil && hw.SNVS.Available() { 177 // use OTPMK if SNVS is secure booted 178 reg.Clear(hw.ctrl, CTRL_AES_KEY_SEL) 179 } else { 180 // set random AES key 181 if err = hw.generateKey(hw.key); err != nil { 182 return 183 } 184 185 // select software AES key 186 reg.Set(hw.ctrl, CTRL_AES_KEY_SEL) 187 } 188 189 // set random nonce for CTR mode 190 if err = hw.generateKey(hw.nonce); err != nil { 191 return 192 } 193 194 // set AES CTR mode 195 reg.Set(hw.ctrl, CTRL_AES_MODE) 196 // set maximum security level 197 reg.SetN(hw.ctrl, CTRL_SECURITY_LEVEL, 0b11, 3) 198 199 // enable 200 reg.Set(hw.ctrl, CTRL_BEE_ENABLE) 201 202 return 203 } 204 205 // Lock restricts BEE registers writing. 206 func (hw *BEE) Lock() { 207 hw.mu.Lock() 208 defer hw.mu.Unlock() 209 210 reg.Set(hw.ctrl, CTRL_CLK_EN_LOCK) 211 reg.Set(hw.ctrl, CTRL_SFTRST_N_LOCK) 212 reg.Set(hw.ctrl, CTRL_AES_MODE_LOCK) 213 reg.SetN(hw.ctrl, CTRL_SECURITY_LEVEL_LOCK, 0b11, 0b11) 214 reg.Set(hw.ctrl, CTRL_AES_KEY_SEL_LOCK) 215 reg.Set(hw.ctrl, CTRL_BEE_ENABLE_LOCK) 216 217 reg.SetN(hw.addr0, 16, 0xffff, 0xffff) 218 reg.SetN(hw.addr1, 16, 0xffff, 0xffff) 219 }