1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-09-19 10:26:10 -04:00
v2fly/external/github.com/lucas-clemente/quic-go/internal/handshake/aead.go

105 lines
2.6 KiB
Go
Raw Normal View History

2018-11-23 11:04:53 -05:00
package handshake
import (
"crypto/cipher"
"encoding/binary"
2019-01-17 09:33:18 -05:00
"v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/protocol"
2018-11-23 11:04:53 -05:00
)
type sealer struct {
2019-01-02 07:01:06 -05:00
aead cipher.AEAD
2019-01-14 14:52:10 -05:00
hpEncrypter cipher.Block
2018-11-23 11:04:53 -05:00
// use a single slice to avoid allocations
nonceBuf []byte
2019-01-14 14:52:10 -05:00
hpMask []byte
2019-01-02 07:01:06 -05:00
// short headers protect 5 bits in the first byte, long headers only 4
is1RTT bool
2018-11-23 11:04:53 -05:00
}
var _ Sealer = &sealer{}
2019-01-14 14:52:10 -05:00
func newSealer(aead cipher.AEAD, hpEncrypter cipher.Block, is1RTT bool) Sealer {
2018-11-23 11:04:53 -05:00
return &sealer{
2019-01-02 07:01:06 -05:00
aead: aead,
nonceBuf: make([]byte, aead.NonceSize()),
is1RTT: is1RTT,
2019-01-14 14:52:10 -05:00
hpEncrypter: hpEncrypter,
hpMask: make([]byte, hpEncrypter.BlockSize()),
2018-11-23 11:04:53 -05:00
}
}
func (s *sealer) Seal(dst, src []byte, pn protocol.PacketNumber, ad []byte) []byte {
binary.BigEndian.PutUint64(s.nonceBuf[len(s.nonceBuf)-8:], uint64(pn))
2019-01-14 14:52:10 -05:00
// The AEAD we're using here will be the qtls.aeadAESGCM13.
// It uses the nonce provided here and XOR it with the IV.
return s.aead.Seal(dst, s.nonceBuf, src, ad)
2019-01-02 07:01:06 -05:00
}
func (s *sealer) EncryptHeader(sample []byte, firstByte *byte, pnBytes []byte) {
2019-01-14 14:52:10 -05:00
if len(sample) != s.hpEncrypter.BlockSize() {
2019-01-02 07:01:06 -05:00
panic("invalid sample size")
}
2019-01-14 14:52:10 -05:00
s.hpEncrypter.Encrypt(s.hpMask, sample)
2019-01-02 07:01:06 -05:00
if s.is1RTT {
2019-01-14 14:52:10 -05:00
*firstByte ^= s.hpMask[0] & 0x1f
2019-01-02 07:01:06 -05:00
} else {
2019-01-14 14:52:10 -05:00
*firstByte ^= s.hpMask[0] & 0xf
2019-01-02 07:01:06 -05:00
}
for i := range pnBytes {
2019-01-14 14:52:10 -05:00
pnBytes[i] ^= s.hpMask[i+1]
2019-01-02 07:01:06 -05:00
}
2018-11-23 11:04:53 -05:00
}
func (s *sealer) Overhead() int {
return s.aead.Overhead()
}
type opener struct {
2019-01-02 07:01:06 -05:00
aead cipher.AEAD
pnDecrypter cipher.Block
2018-11-23 11:04:53 -05:00
// use a single slice to avoid allocations
nonceBuf []byte
2019-01-14 14:52:10 -05:00
hpMask []byte
2019-01-02 07:01:06 -05:00
// short headers protect 5 bits in the first byte, long headers only 4
is1RTT bool
2018-11-23 11:04:53 -05:00
}
var _ Opener = &opener{}
2019-01-14 14:52:10 -05:00
func newOpener(aead cipher.AEAD, pnDecrypter cipher.Block, is1RTT bool) Opener {
2018-11-23 11:04:53 -05:00
return &opener{
2019-01-02 07:01:06 -05:00
aead: aead,
nonceBuf: make([]byte, aead.NonceSize()),
is1RTT: is1RTT,
pnDecrypter: pnDecrypter,
2019-01-14 14:52:10 -05:00
hpMask: make([]byte, pnDecrypter.BlockSize()),
2018-11-23 11:04:53 -05:00
}
}
func (o *opener) Open(dst, src []byte, pn protocol.PacketNumber, ad []byte) ([]byte, error) {
binary.BigEndian.PutUint64(o.nonceBuf[len(o.nonceBuf)-8:], uint64(pn))
2019-01-14 14:52:10 -05:00
// The AEAD we're using here will be the qtls.aeadAESGCM13.
// It uses the nonce provided here and XOR it with the IV.
return o.aead.Open(dst, o.nonceBuf, src, ad)
2019-01-02 07:01:06 -05:00
}
func (o *opener) DecryptHeader(sample []byte, firstByte *byte, pnBytes []byte) {
if len(sample) != o.pnDecrypter.BlockSize() {
panic("invalid sample size")
}
2019-01-14 14:52:10 -05:00
o.pnDecrypter.Encrypt(o.hpMask, sample)
2019-01-02 07:01:06 -05:00
if o.is1RTT {
2019-01-14 14:52:10 -05:00
*firstByte ^= o.hpMask[0] & 0x1f
2019-01-02 07:01:06 -05:00
} else {
2019-01-14 14:52:10 -05:00
*firstByte ^= o.hpMask[0] & 0xf
2019-01-02 07:01:06 -05:00
}
for i := range pnBytes {
2019-01-14 14:52:10 -05:00
pnBytes[i] ^= o.hpMask[i+1]
2019-01-02 07:01:06 -05:00
}
2018-11-23 11:04:53 -05:00
}