github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/quic-go/internal/handshake/retry.go (about) 1 package handshake 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "fmt" 8 "sync" 9 10 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/protocol" 11 ) 12 13 var ( 14 oldRetryAEAD cipher.AEAD // used for QUIC draft versions up to 34 15 retryAEAD cipher.AEAD // used for QUIC draft-34 16 ) 17 18 func init() { 19 oldRetryAEAD = initAEAD([16]byte{0xcc, 0xce, 0x18, 0x7e, 0xd0, 0x9a, 0x09, 0xd0, 0x57, 0x28, 0x15, 0x5a, 0x6c, 0xb9, 0x6b, 0xe1}) 20 retryAEAD = initAEAD([16]byte{0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a, 0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e}) 21 } 22 23 func initAEAD(key [16]byte) cipher.AEAD { 24 aes, err := aes.NewCipher(key[:]) 25 if err != nil { 26 panic(err) 27 } 28 aead, err := cipher.NewGCM(aes) 29 if err != nil { 30 panic(err) 31 } 32 return aead 33 } 34 35 var ( 36 retryBuf bytes.Buffer 37 retryMutex sync.Mutex 38 oldRetryNonce = [12]byte{0xe5, 0x49, 0x30, 0xf9, 0x7f, 0x21, 0x36, 0xf0, 0x53, 0x0a, 0x8c, 0x1c} 39 retryNonce = [12]byte{0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb} 40 ) 41 42 // GetRetryIntegrityTag calculates the integrity tag on a Retry packet 43 func GetRetryIntegrityTag(retry []byte, origDestConnID protocol.ConnectionID, version protocol.VersionNumber) *[16]byte { 44 retryMutex.Lock() 45 retryBuf.WriteByte(uint8(origDestConnID.Len())) 46 retryBuf.Write(origDestConnID.Bytes()) 47 retryBuf.Write(retry) 48 49 var tag [16]byte 50 var sealed []byte 51 if version != protocol.Version1 { 52 sealed = oldRetryAEAD.Seal(tag[:0], oldRetryNonce[:], nil, retryBuf.Bytes()) 53 } else { 54 sealed = retryAEAD.Seal(tag[:0], retryNonce[:], nil, retryBuf.Bytes()) 55 } 56 if len(sealed) != 16 { 57 panic(fmt.Sprintf("unexpected Retry integrity tag length: %d", len(sealed))) 58 } 59 retryBuf.Reset() 60 retryMutex.Unlock() 61 return &tag 62 }