62 lines
1.4 KiB
Go
62 lines
1.4 KiB
Go
package lafsession
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"io"
|
|
|
|
"golang.org/x/crypto/chacha20poly1305"
|
|
"golang.org/x/crypto/hkdf"
|
|
)
|
|
|
|
const (
|
|
keyLen = chacha20poly1305.KeySize
|
|
nonceLen = chacha20poly1305.NonceSize
|
|
tagLen = 16
|
|
)
|
|
|
|
type trafficKeys struct {
|
|
c2s [keyLen]byte
|
|
s2c [keyLen]byte
|
|
}
|
|
|
|
func deriveTrafficKeys(sharedSecret, transcriptHash []byte, version uint16, suite uint16) (*trafficKeys, error) {
|
|
return deriveTrafficKeysImpl(sharedSecret, transcriptHash, version, suite)
|
|
}
|
|
|
|
func deriveTrafficKeysImpl(sharedSecret, transcriptHash []byte, version uint16, suite uint16) (*trafficKeys, error) {
|
|
info := buildHKDFInfo(version, suite, transcriptHash)
|
|
r := hkdf.New(sha256.New, sharedSecret, nil, info)
|
|
var tk trafficKeys
|
|
if _, err := io.ReadFull(r, tk.c2s[:]); err != nil {
|
|
return nil, err
|
|
}
|
|
if _, err := io.ReadFull(r, tk.s2c[:]); err != nil {
|
|
return nil, err
|
|
}
|
|
return &tk, nil
|
|
}
|
|
|
|
func buildHKDFInfo(version, suite uint16, transcriptHash []byte) []byte {
|
|
const label = "lafsession ecdh-aead v1\x00"
|
|
info := make([]byte, 0, len(label)+2+2+len(transcriptHash))
|
|
info = append(info, label...)
|
|
info = append(info, byte(version>>8), byte(version))
|
|
info = append(info, byte(suite>>8), byte(suite))
|
|
info = append(info, transcriptHash...)
|
|
return info
|
|
}
|
|
|
|
func zero(b []byte) {
|
|
for i := range b {
|
|
b[i] = 0
|
|
}
|
|
}
|
|
|
|
func (tk *trafficKeys) wipe() {
|
|
if tk == nil {
|
|
return
|
|
}
|
|
zero(tk.c2s[:])
|
|
zero(tk.s2c[:])
|
|
}
|