aead.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package handshake
  2. import (
  3. "crypto/cipher"
  4. "encoding/binary"
  5. "v2ray.com/core/external/github.com/lucas-clemente/quic-go/internal/protocol"
  6. )
  7. type sealer struct {
  8. aead cipher.AEAD
  9. hpEncrypter cipher.Block
  10. // use a single slice to avoid allocations
  11. nonceBuf []byte
  12. hpMask []byte
  13. // short headers protect 5 bits in the first byte, long headers only 4
  14. is1RTT bool
  15. }
  16. var _ Sealer = &sealer{}
  17. func newSealer(aead cipher.AEAD, hpEncrypter cipher.Block, is1RTT bool) Sealer {
  18. return &sealer{
  19. aead: aead,
  20. nonceBuf: make([]byte, aead.NonceSize()),
  21. is1RTT: is1RTT,
  22. hpEncrypter: hpEncrypter,
  23. hpMask: make([]byte, hpEncrypter.BlockSize()),
  24. }
  25. }
  26. func (s *sealer) Seal(dst, src []byte, pn protocol.PacketNumber, ad []byte) []byte {
  27. binary.BigEndian.PutUint64(s.nonceBuf[len(s.nonceBuf)-8:], uint64(pn))
  28. // The AEAD we're using here will be the qtls.aeadAESGCM13.
  29. // It uses the nonce provided here and XOR it with the IV.
  30. return s.aead.Seal(dst, s.nonceBuf, src, ad)
  31. }
  32. func (s *sealer) EncryptHeader(sample []byte, firstByte *byte, pnBytes []byte) {
  33. if len(sample) != s.hpEncrypter.BlockSize() {
  34. panic("invalid sample size")
  35. }
  36. s.hpEncrypter.Encrypt(s.hpMask, sample)
  37. if s.is1RTT {
  38. *firstByte ^= s.hpMask[0] & 0x1f
  39. } else {
  40. *firstByte ^= s.hpMask[0] & 0xf
  41. }
  42. for i := range pnBytes {
  43. pnBytes[i] ^= s.hpMask[i+1]
  44. }
  45. }
  46. func (s *sealer) Overhead() int {
  47. return s.aead.Overhead()
  48. }
  49. type opener struct {
  50. aead cipher.AEAD
  51. pnDecrypter cipher.Block
  52. // use a single slice to avoid allocations
  53. nonceBuf []byte
  54. hpMask []byte
  55. // short headers protect 5 bits in the first byte, long headers only 4
  56. is1RTT bool
  57. }
  58. var _ Opener = &opener{}
  59. func newOpener(aead cipher.AEAD, pnDecrypter cipher.Block, is1RTT bool) Opener {
  60. return &opener{
  61. aead: aead,
  62. nonceBuf: make([]byte, aead.NonceSize()),
  63. is1RTT: is1RTT,
  64. pnDecrypter: pnDecrypter,
  65. hpMask: make([]byte, pnDecrypter.BlockSize()),
  66. }
  67. }
  68. func (o *opener) Open(dst, src []byte, pn protocol.PacketNumber, ad []byte) ([]byte, error) {
  69. binary.BigEndian.PutUint64(o.nonceBuf[len(o.nonceBuf)-8:], uint64(pn))
  70. // The AEAD we're using here will be the qtls.aeadAESGCM13.
  71. // It uses the nonce provided here and XOR it with the IV.
  72. return o.aead.Open(dst, o.nonceBuf, src, ad)
  73. }
  74. func (o *opener) DecryptHeader(sample []byte, firstByte *byte, pnBytes []byte) {
  75. if len(sample) != o.pnDecrypter.BlockSize() {
  76. panic("invalid sample size")
  77. }
  78. o.pnDecrypter.Encrypt(o.hpMask, sample)
  79. if o.is1RTT {
  80. *firstByte ^= o.hpMask[0] & 0x1f
  81. } else {
  82. *firstByte ^= o.hpMask[0] & 0xf
  83. }
  84. for i := range pnBytes {
  85. pnBytes[i] ^= o.hpMask[i+1]
  86. }
  87. }