github.com/cloudflare/circl@v1.5.0/internal/nist/drbg.go (about)

     1  // Package nist implements helpers to generate NIST's Known Answer Tests (KATs).
     2  package nist
     3  
     4  import (
     5  	"crypto/aes"
     6  )
     7  
     8  // See NIST's PQCgenKAT.c.
     9  type DRBG struct {
    10  	key [32]byte
    11  	v   [16]byte
    12  }
    13  
    14  func (g *DRBG) incV() {
    15  	for j := 15; j >= 0; j-- {
    16  		if g.v[j] == 255 {
    17  			g.v[j] = 0
    18  		} else {
    19  			g.v[j]++
    20  			break
    21  		}
    22  	}
    23  }
    24  
    25  // AES256_CTR_DRBG_Update(pd, &g.key, &g.v).
    26  func (g *DRBG) update(pd *[48]byte) {
    27  	var buf [48]byte
    28  	b, _ := aes.NewCipher(g.key[:])
    29  	for i := 0; i < 3; i++ {
    30  		g.incV()
    31  		b.Encrypt(buf[i*16:(i+1)*16], g.v[:])
    32  	}
    33  	if pd != nil {
    34  		for i := 0; i < 48; i++ {
    35  			buf[i] ^= pd[i]
    36  		}
    37  	}
    38  	copy(g.key[:], buf[:32])
    39  	copy(g.v[:], buf[32:])
    40  }
    41  
    42  // randombyte_init(seed, NULL, 256).
    43  func NewDRBG(seed *[48]byte) (g DRBG) {
    44  	g.update(seed)
    45  	return
    46  }
    47  
    48  // randombytes.
    49  func (g *DRBG) Fill(x []byte) {
    50  	var block [16]byte
    51  
    52  	b, _ := aes.NewCipher(g.key[:])
    53  	for len(x) > 0 {
    54  		g.incV()
    55  		b.Encrypt(block[:], g.v[:])
    56  		if len(x) < 16 {
    57  			copy(x[:], block[:len(x)])
    58  			break
    59  		}
    60  		copy(x[:], block[:])
    61  		x = x[16:]
    62  	}
    63  	g.update(nil)
    64  }