chacha20poly1305_generic.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package chacha20poly1305
  5. import (
  6. "encoding/binary"
  7. "golang.org/x/crypto/chacha20"
  8. "golang.org/x/crypto/internal/alias"
  9. "golang.org/x/crypto/internal/poly1305"
  10. )
  11. func writeWithPadding(p *poly1305.MAC, b []byte) {
  12. p.Write(b)
  13. if rem := len(b) % 16; rem != 0 {
  14. var buf [16]byte
  15. padLen := 16 - rem
  16. p.Write(buf[:padLen])
  17. }
  18. }
  19. func writeUint64(p *poly1305.MAC, n int) {
  20. var buf [8]byte
  21. binary.LittleEndian.PutUint64(buf[:], uint64(n))
  22. p.Write(buf[:])
  23. }
  24. func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
  25. ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
  26. ciphertext, tag := out[:len(plaintext)], out[len(plaintext):]
  27. if alias.InexactOverlap(out, plaintext) {
  28. panic("chacha20poly1305: invalid buffer overlap")
  29. }
  30. var polyKey [32]byte
  31. s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
  32. s.XORKeyStream(polyKey[:], polyKey[:])
  33. s.SetCounter(1) // set the counter to 1, skipping 32 bytes
  34. s.XORKeyStream(ciphertext, plaintext)
  35. p := poly1305.New(&polyKey)
  36. writeWithPadding(p, additionalData)
  37. writeWithPadding(p, ciphertext)
  38. writeUint64(p, len(additionalData))
  39. writeUint64(p, len(plaintext))
  40. p.Sum(tag[:0])
  41. return ret
  42. }
  43. func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
  44. tag := ciphertext[len(ciphertext)-16:]
  45. ciphertext = ciphertext[:len(ciphertext)-16]
  46. var polyKey [32]byte
  47. s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
  48. s.XORKeyStream(polyKey[:], polyKey[:])
  49. s.SetCounter(1) // set the counter to 1, skipping 32 bytes
  50. p := poly1305.New(&polyKey)
  51. writeWithPadding(p, additionalData)
  52. writeWithPadding(p, ciphertext)
  53. writeUint64(p, len(additionalData))
  54. writeUint64(p, len(ciphertext))
  55. ret, out := sliceForAppend(dst, len(ciphertext))
  56. if alias.InexactOverlap(out, ciphertext) {
  57. panic("chacha20poly1305: invalid buffer overlap")
  58. }
  59. if !p.Verify(tag) {
  60. for i := range out {
  61. out[i] = 0
  62. }
  63. return nil, errOpen
  64. }
  65. s.XORKeyStream(out, ciphertext)
  66. return ret, nil
  67. }