package ecdsa
import (
)
type hmacDRBG struct {
newHMAC func(key []byte) *hmac.HMAC
hK *hmac.HMAC
V []byte
reseedCounter uint64
}
const (
reseedInterval = 1 << 48
maxRequestSize = (1 << 19) / 8
)
type plainPersonalizationString []byte
func (plainPersonalizationString) () {}
type blockAlignedPersonalizationString [][]byte
func (blockAlignedPersonalizationString) () {}
type personalizationString interface {
isPersonalizationString()
}
func [ fips140.Hash]( func() , , []byte, personalizationString) *hmacDRBG {
fips140.RecordApproved()
:= &hmacDRBG{
newHMAC: func( []byte) *hmac.HMAC {
return hmac.New(, )
},
}
:= ().Size()
:= make([]byte, )
.V = bytes.Repeat([]byte{0x01}, )
:= hmac.New(, )
.Write(.V)
.Write([]byte{0x00})
.Write()
.Write()
switch s := .(type) {
case plainPersonalizationString:
.Write()
case blockAlignedPersonalizationString:
:= len(.V) + 1 + len() + len()
for , := range {
pad000(, )
.Write()
= len()
}
}
= .Sum([:0])
= hmac.New(, )
.Write(.V)
.V = .Sum(.V[:0])
.Reset()
.Write(.V)
.Write([]byte{0x01})
.Write()
.Write()
switch s := .(type) {
case plainPersonalizationString:
.Write()
case blockAlignedPersonalizationString:
:= len(.V) + 1 + len() + len()
for , := range {
pad000(, )
.Write()
= len()
}
}
= .Sum([:0])
= hmac.New(, )
.Write(.V)
.V = .Sum(.V[:0])
.hK =
.reseedCounter = 1
return
}
func ( func() fips140.Hash, , []byte, []byte) *hmacDRBG {
return newDRBG(, , , plainPersonalizationString())
}
func ( *hmac.HMAC, int) {
:= .BlockSize()
if := % ; != 0 {
.Write(make([]byte, -))
}
}
func ( *hmacDRBG) ( []byte) {
fips140.RecordApproved()
if len() > maxRequestSize {
panic("ecdsa: internal error: request size exceeds maximum")
}
if .reseedCounter > reseedInterval {
panic("ecdsa: reseed interval exceeded")
}
:= 0
for < len() {
.hK.Reset()
.hK.Write(.V)
.V = .hK.Sum(.V[:0])
+= copy([:], .V)
}
.hK.Reset()
.hK.Write(.V)
.hK.Write([]byte{0x00})
:= .hK.Sum(nil)
.hK = .newHMAC()
.hK.Write(.V)
.V = .hK.Sum(.V[:0])
.reseedCounter++
}