chacha_generic.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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 ChaCha20 implements the core ChaCha20 function as specified
  5. // in https://tools.ietf.org/html/rfc7539#section-2.3.
  6. package chacha20
  7. import (
  8. "crypto/cipher"
  9. "encoding/binary"
  10. )
  11. // assert that *Cipher implements cipher.Stream
  12. var _ cipher.Stream = (*Cipher)(nil)
  13. // Cipher is a stateful instance of ChaCha20 using a particular key
  14. // and nonce. A *Cipher implements the cipher.Stream interface.
  15. type Cipher struct {
  16. key [8]uint32
  17. counter uint32 // incremented after each block
  18. nonce [3]uint32
  19. buf [bufSize]byte // buffer for unused keystream bytes
  20. len int // number of unused keystream bytes at end of buf
  21. }
  22. // New creates a new ChaCha20 stream cipher with the given key and nonce.
  23. // The initial counter value is set to 0.
  24. func New(key [8]uint32, nonce [3]uint32) *Cipher {
  25. return &Cipher{key: key, nonce: nonce}
  26. }
  27. // XORKeyStream XORs each byte in the given slice with a byte from the
  28. // cipher's key stream. Dst and src must overlap entirely or not at all.
  29. //
  30. // If len(dst) < len(src), XORKeyStream will panic. It is acceptable
  31. // to pass a dst bigger than src, and in that case, XORKeyStream will
  32. // only update dst[:len(src)] and will not touch the rest of dst.
  33. //
  34. // Multiple calls to XORKeyStream behave as if the concatenation of
  35. // the src buffers was passed in a single run. That is, Cipher
  36. // maintains state and does not reset at each XORKeyStream call.
  37. func (s *Cipher) XORKeyStream(dst, src []byte) {
  38. // xor src with buffered keystream first
  39. if s.len != 0 {
  40. buf := s.buf[len(s.buf)-s.len:]
  41. if len(src) < len(buf) {
  42. buf = buf[:len(src)]
  43. }
  44. td, ts := dst[:len(buf)], src[:len(buf)] // BCE hint
  45. for i, b := range buf {
  46. td[i] = ts[i] ^ b
  47. }
  48. s.len -= len(buf)
  49. if s.len != 0 {
  50. return
  51. }
  52. s.buf = [len(s.buf)]byte{} // zero the empty buffer
  53. src = src[len(buf):]
  54. dst = dst[len(buf):]
  55. }
  56. if len(src) == 0 {
  57. return
  58. }
  59. if haveAsm {
  60. s.xorKeyStreamAsm(dst, src)
  61. return
  62. }
  63. // set up a 64-byte buffer to pad out the final block if needed
  64. // (hoisted out of the main loop to avoid spills)
  65. rem := len(src) % 64 // length of final block
  66. fin := len(src) - rem // index of final block
  67. if rem > 0 {
  68. copy(s.buf[len(s.buf)-64:], src[fin:])
  69. }
  70. // qr calculates a quarter round
  71. qr := func(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
  72. a += b
  73. d ^= a
  74. d = (d << 16) | (d >> 16)
  75. c += d
  76. b ^= c
  77. b = (b << 12) | (b >> 20)
  78. a += b
  79. d ^= a
  80. d = (d << 8) | (d >> 24)
  81. c += d
  82. b ^= c
  83. b = (b << 7) | (b >> 25)
  84. return a, b, c, d
  85. }
  86. // ChaCha20 constants
  87. const (
  88. j0 = 0x61707865
  89. j1 = 0x3320646e
  90. j2 = 0x79622d32
  91. j3 = 0x6b206574
  92. )
  93. // pre-calculate most of the first round
  94. s1, s5, s9, s13 := qr(j1, s.key[1], s.key[5], s.nonce[0])
  95. s2, s6, s10, s14 := qr(j2, s.key[2], s.key[6], s.nonce[1])
  96. s3, s7, s11, s15 := qr(j3, s.key[3], s.key[7], s.nonce[2])
  97. n := len(src)
  98. src, dst = src[:n:n], dst[:n:n] // BCE hint
  99. for i := 0; i < n; i += 64 {
  100. // calculate the remainder of the first round
  101. s0, s4, s8, s12 := qr(j0, s.key[0], s.key[4], s.counter)
  102. // execute the second round
  103. x0, x5, x10, x15 := qr(s0, s5, s10, s15)
  104. x1, x6, x11, x12 := qr(s1, s6, s11, s12)
  105. x2, x7, x8, x13 := qr(s2, s7, s8, s13)
  106. x3, x4, x9, x14 := qr(s3, s4, s9, s14)
  107. // execute the remaining 18 rounds
  108. for i := 0; i < 9; i++ {
  109. x0, x4, x8, x12 = qr(x0, x4, x8, x12)
  110. x1, x5, x9, x13 = qr(x1, x5, x9, x13)
  111. x2, x6, x10, x14 = qr(x2, x6, x10, x14)
  112. x3, x7, x11, x15 = qr(x3, x7, x11, x15)
  113. x0, x5, x10, x15 = qr(x0, x5, x10, x15)
  114. x1, x6, x11, x12 = qr(x1, x6, x11, x12)
  115. x2, x7, x8, x13 = qr(x2, x7, x8, x13)
  116. x3, x4, x9, x14 = qr(x3, x4, x9, x14)
  117. }
  118. x0 += j0
  119. x1 += j1
  120. x2 += j2
  121. x3 += j3
  122. x4 += s.key[0]
  123. x5 += s.key[1]
  124. x6 += s.key[2]
  125. x7 += s.key[3]
  126. x8 += s.key[4]
  127. x9 += s.key[5]
  128. x10 += s.key[6]
  129. x11 += s.key[7]
  130. x12 += s.counter
  131. x13 += s.nonce[0]
  132. x14 += s.nonce[1]
  133. x15 += s.nonce[2]
  134. // increment the counter
  135. s.counter += 1
  136. if s.counter == 0 {
  137. panic("chacha20: counter overflow")
  138. }
  139. // pad to 64 bytes if needed
  140. in, out := src[i:], dst[i:]
  141. if i == fin {
  142. // src[fin:] has already been copied into s.buf before
  143. // the main loop
  144. in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:]
  145. }
  146. in, out = in[:64], out[:64] // BCE hint
  147. // XOR the key stream with the source and write out the result
  148. xor(out[0:], in[0:], x0)
  149. xor(out[4:], in[4:], x1)
  150. xor(out[8:], in[8:], x2)
  151. xor(out[12:], in[12:], x3)
  152. xor(out[16:], in[16:], x4)
  153. xor(out[20:], in[20:], x5)
  154. xor(out[24:], in[24:], x6)
  155. xor(out[28:], in[28:], x7)
  156. xor(out[32:], in[32:], x8)
  157. xor(out[36:], in[36:], x9)
  158. xor(out[40:], in[40:], x10)
  159. xor(out[44:], in[44:], x11)
  160. xor(out[48:], in[48:], x12)
  161. xor(out[52:], in[52:], x13)
  162. xor(out[56:], in[56:], x14)
  163. xor(out[60:], in[60:], x15)
  164. }
  165. // copy any trailing bytes out of the buffer and into dst
  166. if rem != 0 {
  167. s.len = 64 - rem
  168. copy(dst[fin:], s.buf[len(s.buf)-64:])
  169. }
  170. }
  171. // Advance discards bytes in the key stream until the next 64 byte block
  172. // boundary is reached and updates the counter accordingly. If the key
  173. // stream is already at a block boundary no bytes will be discarded and
  174. // the counter will be unchanged.
  175. func (s *Cipher) Advance() {
  176. s.len -= s.len % 64
  177. if s.len == 0 {
  178. s.buf = [len(s.buf)]byte{}
  179. }
  180. }
  181. // XORKeyStream crypts bytes from in to out using the given key and counters.
  182. // In and out must overlap entirely or not at all. Counter contains the raw
  183. // ChaCha20 counter bytes (i.e. block counter followed by nonce).
  184. func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
  185. s := Cipher{
  186. key: [8]uint32{
  187. binary.LittleEndian.Uint32(key[0:4]),
  188. binary.LittleEndian.Uint32(key[4:8]),
  189. binary.LittleEndian.Uint32(key[8:12]),
  190. binary.LittleEndian.Uint32(key[12:16]),
  191. binary.LittleEndian.Uint32(key[16:20]),
  192. binary.LittleEndian.Uint32(key[20:24]),
  193. binary.LittleEndian.Uint32(key[24:28]),
  194. binary.LittleEndian.Uint32(key[28:32]),
  195. },
  196. nonce: [3]uint32{
  197. binary.LittleEndian.Uint32(counter[4:8]),
  198. binary.LittleEndian.Uint32(counter[8:12]),
  199. binary.LittleEndian.Uint32(counter[12:16]),
  200. },
  201. counter: binary.LittleEndian.Uint32(counter[0:4]),
  202. }
  203. s.XORKeyStream(out, in)
  204. }