stateless_reset.go 970 B

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. package quic
  2. import (
  3. "crypto/hmac"
  4. "crypto/rand"
  5. "crypto/sha256"
  6. "hash"
  7. "sync"
  8. "github.com/Psiphon-Labs/quic-go/internal/protocol"
  9. )
  10. type statelessResetter struct {
  11. mx sync.Mutex
  12. h hash.Hash
  13. }
  14. // newStatelessRetter creates a new stateless reset generator.
  15. // It is valid to use a nil key. In that case, a random key will be used.
  16. // This makes is impossible for on-path attackers to shut down established connections.
  17. func newStatelessResetter(key *StatelessResetKey) *statelessResetter {
  18. var h hash.Hash
  19. if key != nil {
  20. h = hmac.New(sha256.New, key[:])
  21. } else {
  22. b := make([]byte, 32)
  23. _, _ = rand.Read(b)
  24. h = hmac.New(sha256.New, b)
  25. }
  26. return &statelessResetter{h: h}
  27. }
  28. func (r *statelessResetter) GetStatelessResetToken(connID protocol.ConnectionID) protocol.StatelessResetToken {
  29. r.mx.Lock()
  30. defer r.mx.Unlock()
  31. var token protocol.StatelessResetToken
  32. r.h.Write(connID.Bytes())
  33. copy(token[:], r.h.Sum(nil))
  34. r.h.Reset()
  35. return token
  36. }