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  }