github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/soc/imx6/rngb/rngb.go (about) 1 // NXP Random Number Generator (RNGB) driver 2 // https://github.com/f-secure-foundry/tamago 3 // 4 // Copyright (c) F-Secure Corporation 5 // https://foundry.f-secure.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 rngb implements a driver for the NXP True Random Number Generator 11 // (RNGB) included in i.MX6ULL/i.MX6ULZ SoCs. 12 // 13 // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as 14 // supported by the TamaGo framework for bare metal Go on ARM SoCs, see 15 // https://github.com/f-secure-foundry/tamago. 16 package rngb 17 18 import ( 19 "sync" 20 21 "github.com/f-secure-foundry/tamago/internal/reg" 22 ) 23 24 // RNGB registers 25 const ( 26 RNG_BASE = 0x02284000 27 28 RNG_CMD = RNG_BASE + 0x04 29 RNG_CMD_SR = 6 30 RNG_CMD_CE = 5 31 RNG_CMD_CI = 4 32 RNG_CMD_GS = 1 33 RNG_CMD_ST = 0 34 35 RNG_CR = RNG_BASE + 0x08 36 RNG_CR_AR = 4 37 RNG_CR_GS = 1 38 39 RNG_SR = RNG_BASE + 0x0c 40 RNG_SR_ST_PF = 21 41 RNG_SR_ERR = 16 42 RNG_SR_FIFO_LVL = 8 43 RNG_SR_SDN = 5 44 RNG_SR_STDN = 4 45 46 RNG_ESR = RNG_BASE + 0x10 47 RNG_OUT = RNG_BASE + 0x14 48 ) 49 50 var mux sync.Mutex 51 52 // Reset resets the RNGB module. 53 func Reset() { 54 mux.Lock() 55 defer mux.Unlock() 56 57 // soft reset RNGB 58 reg.Set(RNG_CMD, RNG_CMD_SR) 59 } 60 61 // Init initializes the RNGB module with automatic seeding. 62 func Init() { 63 mux.Lock() 64 defer mux.Unlock() 65 66 // p3105, 44.5.2 Automatic seeding, IMX6ULLRM 67 68 // clear errors 69 reg.Set(RNG_CMD, RNG_CMD_CE) 70 71 // soft reset RNGB 72 reg.Set(RNG_CMD, RNG_CMD_SR) 73 74 // perform self-test 75 reg.Set(RNG_CMD, RNG_CMD_ST) 76 77 for reg.Get(RNG_SR, RNG_SR_STDN, 1) != 1 { 78 // reg.Wait cannot be used before runtime initialization 79 } 80 81 if reg.Get(RNG_SR, RNG_SR_ERR, 1) != 0 || reg.Get(RNG_SR, RNG_SR_ST_PF, 1) != 0 { 82 panic("imx6_rng: self-test failure\n") 83 } 84 85 // enable auto-reseed 86 reg.Set(RNG_CR, RNG_CR_AR) 87 // generate a seed 88 reg.Set(RNG_CMD, RNG_CR_GS) 89 90 for reg.Get(RNG_SR, RNG_SR_SDN, 1) != 1 { 91 // reg.Wait cannot be used before runtime initialization 92 } 93 94 // clear interrupts 95 reg.Set(RNG_CMD, RNG_CMD_CI) 96 } 97 98 // GetRandomData returns len(b) random bytes gathered from the RNGB module. 99 func GetRandomData(b []byte) { 100 read := 0 101 need := len(b) 102 103 for read < need { 104 if reg.Get(RNG_SR, RNG_SR_ERR, 1) != 0 { 105 panic("imx6_rng: error during getRandomData\n") 106 } 107 108 if reg.Get(RNG_SR, RNG_SR_FIFO_LVL, 0b1111) > 0 { 109 read = Fill(b, read, reg.Read(RNG_OUT)) 110 } 111 } 112 } 113 114 func Fill(b []byte, index int, val uint32) int { 115 shift := 0 116 limit := len(b) 117 118 for (index < limit) && (shift <= 24) { 119 b[index] = byte((val >> shift) & 0xff) 120 index += 1 121 shift += 8 122 } 123 124 return index 125 }