package tls13
import (
"crypto/internal/fips140"
"crypto/internal/fips140/hkdf"
"crypto/internal/fips140deps/byteorder"
)
func ExpandLabel [H fips140 .Hash ](hash func () H , secret []byte , label string , context []byte , length int ) []byte {
if len ("tls13 " )+len (label ) > 255 || len (context ) > 255 {
panic ("tls13: label or context too long" )
}
hkdfLabel := make ([]byte , 0 , 2 +1 +len ("tls13 " )+len (label )+1 +len (context ))
hkdfLabel = byteorder .BEAppendUint16 (hkdfLabel , uint16 (length ))
hkdfLabel = append (hkdfLabel , byte (len ("tls13 " )+len (label )))
hkdfLabel = append (hkdfLabel , "tls13 " ...)
hkdfLabel = append (hkdfLabel , label ...)
hkdfLabel = append (hkdfLabel , byte (len (context )))
hkdfLabel = append (hkdfLabel , context ...)
return hkdf .Expand (hash , secret , string (hkdfLabel ), length )
}
func extract[H fips140 .Hash ](hash func () H , newSecret , currentSecret []byte ) []byte {
if newSecret == nil {
newSecret = make ([]byte , hash ().Size ())
}
return hkdf .Extract (hash , newSecret , currentSecret )
}
func deriveSecret[H fips140 .Hash ](hash func () H , secret []byte , label string , transcript fips140 .Hash ) []byte {
if transcript == nil {
transcript = hash ()
}
return ExpandLabel (hash , secret , label , transcript .Sum (nil ), transcript .Size ())
}
const (
resumptionBinderLabel = "res binder"
clientEarlyTrafficLabel = "c e traffic"
clientHandshakeTrafficLabel = "c hs traffic"
serverHandshakeTrafficLabel = "s hs traffic"
clientApplicationTrafficLabel = "c ap traffic"
serverApplicationTrafficLabel = "s ap traffic"
earlyExporterLabel = "e exp master"
exporterLabel = "exp master"
resumptionLabel = "res master"
)
type EarlySecret struct {
secret []byte
hash func () fips140 .Hash
}
func NewEarlySecret [H fips140 .Hash ](hash func () H , psk []byte ) *EarlySecret {
return &EarlySecret {
secret : extract (hash , psk , nil ),
hash : func () fips140 .Hash { return hash () },
}
}
func (s *EarlySecret ) ResumptionBinderKey () []byte {
return deriveSecret (s .hash , s .secret , resumptionBinderLabel , nil )
}
func (s *EarlySecret ) ClientEarlyTrafficSecret (transcript fips140 .Hash ) []byte {
return deriveSecret (s .hash , s .secret , clientEarlyTrafficLabel , transcript )
}
type HandshakeSecret struct {
secret []byte
hash func () fips140 .Hash
}
func (s *EarlySecret ) HandshakeSecret (sharedSecret []byte ) *HandshakeSecret {
derived := deriveSecret (s .hash , s .secret , "derived" , nil )
return &HandshakeSecret {
secret : extract (s .hash , sharedSecret , derived ),
hash : s .hash ,
}
}
func (s *HandshakeSecret ) ClientHandshakeTrafficSecret (transcript fips140 .Hash ) []byte {
return deriveSecret (s .hash , s .secret , clientHandshakeTrafficLabel , transcript )
}
func (s *HandshakeSecret ) ServerHandshakeTrafficSecret (transcript fips140 .Hash ) []byte {
return deriveSecret (s .hash , s .secret , serverHandshakeTrafficLabel , transcript )
}
type MasterSecret struct {
secret []byte
hash func () fips140 .Hash
}
func (s *HandshakeSecret ) MasterSecret () *MasterSecret {
derived := deriveSecret (s .hash , s .secret , "derived" , nil )
return &MasterSecret {
secret : extract (s .hash , nil , derived ),
hash : s .hash ,
}
}
func (s *MasterSecret ) ClientApplicationTrafficSecret (transcript fips140 .Hash ) []byte {
return deriveSecret (s .hash , s .secret , clientApplicationTrafficLabel , transcript )
}
func (s *MasterSecret ) ServerApplicationTrafficSecret (transcript fips140 .Hash ) []byte {
return deriveSecret (s .hash , s .secret , serverApplicationTrafficLabel , transcript )
}
func (s *MasterSecret ) ResumptionMasterSecret (transcript fips140 .Hash ) []byte {
return deriveSecret (s .hash , s .secret , resumptionLabel , transcript )
}
type ExporterMasterSecret struct {
secret []byte
hash func () fips140 .Hash
}
func (s *MasterSecret ) ExporterMasterSecret (transcript fips140 .Hash ) *ExporterMasterSecret {
return &ExporterMasterSecret {
secret : deriveSecret (s .hash , s .secret , exporterLabel , transcript ),
hash : s .hash ,
}
}
func (s *EarlySecret ) EarlyExporterMasterSecret (transcript fips140 .Hash ) *ExporterMasterSecret {
return &ExporterMasterSecret {
secret : deriveSecret (s .hash , s .secret , earlyExporterLabel , transcript ),
hash : s .hash ,
}
}
func (s *ExporterMasterSecret ) Exporter (label string , context []byte , length int ) []byte {
secret := deriveSecret (s .hash , s .secret , label , nil )
h := s .hash ()
h .Write (context )
return ExpandLabel (s .hash , secret , "exporter" , h .Sum (nil ), length )
}
func TestingOnlyExporterSecret (s *ExporterMasterSecret ) []byte {
return s .secret
}
The pages are generated with Golds v0.7.3-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .