mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-23 00:51:29 +00:00
149 lines
3.7 KiB
Go
149 lines
3.7 KiB
Go
|
package qtls
|
||
|
|
||
|
import (
|
||
|
"crypto"
|
||
|
"crypto/aes"
|
||
|
"crypto/cipher"
|
||
|
"encoding/binary"
|
||
|
"io"
|
||
|
|
||
|
"golang.org/x/crypto/hkdf"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
VersionDraft29 = 0xff00001d
|
||
|
Version1 = 0x1
|
||
|
Version2 = 0x709a50c4
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
SaltOld = []byte{0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99}
|
||
|
SaltV1 = []byte{0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a}
|
||
|
SaltV2 = []byte{0xa7, 0x07, 0xc2, 0x03, 0xa5, 0x9b, 0x47, 0x18, 0x4a, 0x1d, 0x62, 0xca, 0x57, 0x04, 0x06, 0xea, 0x7a, 0xe3, 0xe5, 0xd3}
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
HKDFLabelKeyV1 = "quic key"
|
||
|
HKDFLabelKeyV2 = "quicv2 key"
|
||
|
HKDFLabelIVV1 = "quic iv"
|
||
|
HKDFLabelIVV2 = "quicv2 iv"
|
||
|
HKDFLabelHeaderProtectionV1 = "quic hp"
|
||
|
HKDFLabelHeaderProtectionV2 = "quicv2 hp"
|
||
|
)
|
||
|
|
||
|
func AEADAESGCMTLS13(key, nonceMask []byte) cipher.AEAD {
|
||
|
if len(nonceMask) != 12 {
|
||
|
panic("tls: internal error: wrong nonce length")
|
||
|
}
|
||
|
aes, err := aes.NewCipher(key)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
aead, err := cipher.NewGCM(aes)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
ret := &xorNonceAEAD{aead: aead}
|
||
|
copy(ret.nonceMask[:], nonceMask)
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
type xorNonceAEAD struct {
|
||
|
nonceMask [12]byte
|
||
|
aead cipher.AEAD
|
||
|
}
|
||
|
|
||
|
func (f *xorNonceAEAD) NonceSize() int { return 8 } // 64-bit sequence number
|
||
|
func (f *xorNonceAEAD) Overhead() int { return f.aead.Overhead() }
|
||
|
func (f *xorNonceAEAD) explicitNonceLen() int { return 0 }
|
||
|
|
||
|
func (f *xorNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
|
||
|
for i, b := range nonce {
|
||
|
f.nonceMask[4+i] ^= b
|
||
|
}
|
||
|
result := f.aead.Seal(out, f.nonceMask[:], plaintext, additionalData)
|
||
|
for i, b := range nonce {
|
||
|
f.nonceMask[4+i] ^= b
|
||
|
}
|
||
|
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
func (f *xorNonceAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||
|
for i, b := range nonce {
|
||
|
f.nonceMask[4+i] ^= b
|
||
|
}
|
||
|
result, err := f.aead.Open(out, f.nonceMask[:], ciphertext, additionalData)
|
||
|
for i, b := range nonce {
|
||
|
f.nonceMask[4+i] ^= b
|
||
|
}
|
||
|
|
||
|
return result, err
|
||
|
}
|
||
|
|
||
|
func HKDFExpandLabel(hash crypto.Hash, secret, context []byte, label string, length int) []byte {
|
||
|
b := make([]byte, 3, 3+6+len(label)+1+len(context))
|
||
|
binary.BigEndian.PutUint16(b, uint16(length))
|
||
|
b[2] = uint8(6 + len(label))
|
||
|
b = append(b, []byte("tls13 ")...)
|
||
|
b = append(b, []byte(label)...)
|
||
|
b = b[:3+6+len(label)+1]
|
||
|
b[3+6+len(label)] = uint8(len(context))
|
||
|
b = append(b, context...)
|
||
|
out := make([]byte, length)
|
||
|
n, err := hkdf.Expand(hash.New, secret, b).Read(out)
|
||
|
if err != nil || n != length {
|
||
|
panic("quic: HKDF-Expand-Label invocation failed unexpectedly")
|
||
|
}
|
||
|
return out
|
||
|
}
|
||
|
|
||
|
func ReadUvarint(r io.ByteReader) (uint64, error) {
|
||
|
firstByte, err := r.ReadByte()
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
// the first two bits of the first byte encode the length
|
||
|
len := 1 << ((firstByte & 0xc0) >> 6)
|
||
|
b1 := firstByte & (0xff - 0xc0)
|
||
|
if len == 1 {
|
||
|
return uint64(b1), nil
|
||
|
}
|
||
|
b2, err := r.ReadByte()
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
if len == 2 {
|
||
|
return uint64(b2) + uint64(b1)<<8, nil
|
||
|
}
|
||
|
b3, err := r.ReadByte()
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
b4, err := r.ReadByte()
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
if len == 4 {
|
||
|
return uint64(b4) + uint64(b3)<<8 + uint64(b2)<<16 + uint64(b1)<<24, nil
|
||
|
}
|
||
|
b5, err := r.ReadByte()
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
b6, err := r.ReadByte()
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
b7, err := r.ReadByte()
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
b8, err := r.ReadByte()
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
return uint64(b8) + uint64(b7)<<8 + uint64(b6)<<16 + uint64(b5)<<24 + uint64(b4)<<32 + uint64(b3)<<40 + uint64(b2)<<48 + uint64(b1)<<56, nil
|
||
|
}
|