github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/caam/rng.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  	"github.com/usbarmory/tamago/bits"
    14  	"github.com/usbarmory/tamago/internal/reg"
    15  	"github.com/usbarmory/tamago/internal/rng"
    16  )
    17  
    18  func (hw *CAAM) initRNG() {
    19  	// initialize RNG
    20  	op1 := Operation{}
    21  	op1.SetDefaults()
    22  	op1.OpType(OPTYPE_ALG_CLASS1)
    23  	op1.Algorithm(ALG_RNG, 0)
    24  	op1.State(AS_INITIALIZE)
    25  
    26  	// enable Prediction Resistance (PR)
    27  	bits.Set(&op1.Word0, 1)
    28  
    29  	// wait for previous operation
    30  	jmp := Jump{}
    31  	jmp.SetDefaults()
    32  	jmp.Class(1)
    33  	jmp.Offset(1)
    34  
    35  	// clear Class 1 Mode Register
    36  	c1m := Load{}
    37  	c1m.SetDefaults()
    38  	c1m.Destination(CLRW)
    39  	c1m.Immediate(1 << C0CWR_C1M)
    40  
    41  	// initialize JDKEK, TDKEK and TDSK
    42  	op2 := Operation{}
    43  	op2.SetDefaults()
    44  	op2.OpType(OPTYPE_ALG_CLASS1)
    45  	op2.Algorithm(ALG_RNG, (1 << AAI_RNG_SK))
    46  
    47  	jd := op1.Bytes()
    48  	jd = append(jd, jmp.Bytes()...)
    49  	jd = append(jd, c1m.Bytes()...)
    50  	jd = append(jd, op2.Bytes()...)
    51  
    52  	hw.jr.add(nil, jd)
    53  }
    54  
    55  // GetRandomData returns len(b) random bytes gathered from the CAAM TRNG.
    56  func (hw *CAAM) GetRandomData(b []byte) {
    57  	hw.Lock()
    58  	defer hw.Unlock()
    59  
    60  	// TRNG access through RTENT registers prevents RNG access in CAAM
    61  	// commands, enable only as needed.
    62  	reg.Set(hw.rtmctl, RTMCTL_TRNG_ACC)
    63  	defer reg.Clear(hw.rtmctl, RTMCTL_TRNG_ACC)
    64  
    65  	read := 0
    66  	need := len(b)
    67  
    68  	for read < need {
    69  		if hw.rtenta == hw.rtent0 {
    70  			for reg.Get(hw.rtmctl, RTMCTL_ENT_VAL, 1) == 0 {
    71  				// wait for valid entropy
    72  			}
    73  		}
    74  
    75  		read = rng.Fill(b, read, reg.Read(hw.rtenta))
    76  
    77  		if hw.rtenta == hw.rtent15 {
    78  			hw.rtenta = hw.rtent0
    79  		} else {
    80  			hw.rtenta += 4
    81  		}
    82  	}
    83  }