You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

413 lines
8.2 KiB

  1. // Use of this source code is governed by an ISC
  2. // license that can be found in the LICENSE file.
  3. package echo
  4. import (
  5. "fmt"
  6. "gitlab.com/nitya-sattva/go-x11/aesr"
  7. "gitlab.com/nitya-sattva/go-x11/hash"
  8. )
  9. // HashSize holds the size of a hash in bytes.
  10. const HashSize = uintptr(64)
  11. // BlockSize holds the size of a block in bytes.
  12. const BlockSize = uintptr(128)
  13. ////////////////
  14. type digest struct {
  15. ptr uintptr
  16. h [8][2]uint64
  17. c [4]uint32
  18. b [BlockSize]byte
  19. }
  20. // New returns a new digest compute a ECHO512 hash.
  21. func New() hash.Digest {
  22. ref := &digest{}
  23. ref.Reset()
  24. return ref
  25. }
  26. ////////////////
  27. // Reset resets the digest to its initial state.
  28. func (ref *digest) Reset() {
  29. ref.ptr = 0
  30. ref.h[0][0] = uint64(8 * HashSize)
  31. ref.h[0][1] = 0
  32. ref.h[1][0] = uint64(8 * HashSize)
  33. ref.h[1][1] = 0
  34. ref.h[2][0] = uint64(8 * HashSize)
  35. ref.h[2][1] = 0
  36. ref.h[3][0] = uint64(8 * HashSize)
  37. ref.h[3][1] = 0
  38. ref.h[4][0] = uint64(8 * HashSize)
  39. ref.h[4][1] = 0
  40. ref.h[5][0] = uint64(8 * HashSize)
  41. ref.h[5][1] = 0
  42. ref.h[6][0] = uint64(8 * HashSize)
  43. ref.h[6][1] = 0
  44. ref.h[7][0] = uint64(8 * HashSize)
  45. ref.h[7][1] = 0
  46. memset32(ref.c[:], 0)
  47. }
  48. // Sum appends the current hash to dst and returns the result
  49. // as a slice. It does not change the underlying hash state.
  50. func (ref *digest) Sum(dst []byte) []byte {
  51. dgt := *ref
  52. hsh := [64]byte{}
  53. dgt.Close(hsh[:], 0, 0)
  54. return append(dst, hsh[:]...)
  55. }
  56. // Write more data to the running hash, never returns an error.
  57. func (ref *digest) Write(src []byte) (int, error) {
  58. sln := uintptr(len(src))
  59. fln := len(src)
  60. ptr := ref.ptr
  61. if sln < (BlockSize - ptr) {
  62. copy(ref.b[ptr:], src)
  63. ref.ptr += sln
  64. return int(sln), nil
  65. }
  66. for sln > 0 {
  67. cln := BlockSize - ptr
  68. if cln > sln {
  69. cln = sln
  70. }
  71. sln -= cln
  72. copy(ref.b[ptr:], src[:cln])
  73. src = src[cln:]
  74. ptr += cln
  75. if ptr == BlockSize {
  76. ref.c[0] += 1024
  77. if ref.c[0] < 1024 {
  78. ref.c[1] += 1
  79. if ref.c[1] == 0 {
  80. ref.c[2] += 1
  81. if ref.c[2] == 0 {
  82. ref.c[3] += 1
  83. }
  84. }
  85. }
  86. compress(ref)
  87. ptr = 0
  88. }
  89. }
  90. ref.ptr = ptr
  91. return fln, nil
  92. }
  93. // Close the digest by writing the last bits and storing the hash
  94. // in dst. This prepares the digest for reuse by calling reset. A call
  95. // to Close with a dst that is smaller then HashSize will return an error.
  96. func (ref *digest) Close(dst []byte, bits uint8, bcnt uint8) error {
  97. if ln := len(dst); HashSize > uintptr(ln) {
  98. return fmt.Errorf("Echo Close: dst min length: %d, got %d", HashSize, ln)
  99. }
  100. ptr := ref.ptr
  101. buf := ref.b[:]
  102. eln := uint32(ptr<<3) + uint32(bcnt)
  103. ref.c[0] += eln
  104. if ref.c[0] < eln {
  105. ref.c[1] += 1
  106. if ref.c[1] == 0 {
  107. ref.c[2] += 1
  108. if ref.c[2] == 0 {
  109. ref.c[3] += 1
  110. }
  111. }
  112. }
  113. var tmp [64]uint8
  114. encUInt32le(tmp[:], ref.c[0])
  115. encUInt32le(tmp[4:], ref.c[1])
  116. encUInt32le(tmp[8:], ref.c[2])
  117. encUInt32le(tmp[12:], ref.c[3])
  118. if eln == 0 {
  119. memset32(ref.c[:], 0)
  120. }
  121. {
  122. off := uint8(0x80) >> bcnt
  123. buf[ptr] = uint8((bits & -off) | off)
  124. }
  125. ptr += 1
  126. memset8(buf[ptr:], 0)
  127. if ptr > (BlockSize - 18) {
  128. compress(ref)
  129. memset8(buf[:], 0)
  130. memset32(ref.c[:], 0)
  131. }
  132. encUInt16le(buf[(BlockSize-18):], uint16(16<<5))
  133. copy(buf[(BlockSize-16):], tmp[:])
  134. compress(ref)
  135. h := ref.h[:]
  136. for x := uintptr(0); x < 4; x++ {
  137. for y := uintptr(0); y < 2; y++ {
  138. encUInt64le(dst[(((x*2)+y)*8):], h[x][y])
  139. }
  140. }
  141. ref.Reset()
  142. return nil
  143. }
  144. // Size returns the number of bytes required to store the hash.
  145. func (*digest) Size() int {
  146. return int(HashSize)
  147. }
  148. // BlockSize returns the block size of the hash.
  149. func (*digest) BlockSize() int {
  150. return int(BlockSize)
  151. }
  152. ////////////////
  153. func memset8(dst []byte, src byte) {
  154. for i := range dst {
  155. dst[i] = src
  156. }
  157. }
  158. func memset32(dst []uint32, src uint32) {
  159. for i := range dst {
  160. dst[i] = src
  161. }
  162. }
  163. func compress(ref *digest) {
  164. var w [16][2]uint64
  165. k0 := ref.c[0]
  166. k1 := ref.c[1]
  167. k2 := ref.c[2]
  168. k3 := ref.c[3]
  169. for i := uintptr(0); i < 8; i++ {
  170. w[i][0] = ref.h[i][0]
  171. w[i+8][0] = decUInt64le(ref.b[(16 * i):])
  172. w[i][1] = ref.h[i][1]
  173. w[i+8][1] = decUInt64le(ref.b[((16 * i) + 8):])
  174. }
  175. var a0, a1, a2 uint64
  176. var b0, b1, b2 uint64
  177. var w0, w1, w2, w3 uint64
  178. var x0, x1, x2, x3 uint32
  179. var y0, y1, y2, y3 uint32
  180. for u := uintptr(0); u < 10; u++ {
  181. for n := uintptr(0); n < 16; n++ {
  182. x0 = uint32(w[n][0])
  183. x1 = uint32(w[n][0] >> 32)
  184. x2 = uint32(w[n][1])
  185. x3 = uint32(w[n][1] >> 32)
  186. y0, y1, y2, y3 = aesr.Round32ble(
  187. x0, x1, x2, x3,
  188. k0, k1, k2, k3,
  189. )
  190. x0, x1, x2, x3 = aesr.Round32ble(
  191. y0, y1, y2, y3,
  192. 0, 0, 0, 0,
  193. )
  194. w[n][0] = uint64(x0) | (uint64(x1) << 32)
  195. w[n][1] = uint64(x2) | (uint64(x3) << 32)
  196. k0 += 1
  197. if k0 == 0 {
  198. k1 += 1
  199. if k1 == 0 {
  200. k2 += 1
  201. if k2 == 0 {
  202. k3 += 1
  203. }
  204. }
  205. }
  206. }
  207. a0 = w[1][0]
  208. w[1][0] = w[5][0]
  209. w[5][0] = w[9][0]
  210. w[9][0] = w[13][0]
  211. w[13][0] = a0
  212. a0 = w[1][1]
  213. w[1][1] = w[5][1]
  214. w[5][1] = w[9][1]
  215. w[9][1] = w[13][1]
  216. w[13][1] = a0
  217. a0 = w[2][0]
  218. w[2][0] = w[10][0]
  219. w[10][0] = a0
  220. a0 = w[6][0]
  221. w[6][0] = w[14][0]
  222. w[14][0] = a0
  223. a0 = w[2][1]
  224. w[2][1] = w[10][1]
  225. w[10][1] = a0
  226. a0 = w[6][1]
  227. w[6][1] = w[14][1]
  228. w[14][1] = a0
  229. a0 = w[15][0]
  230. w[15][0] = w[11][0]
  231. w[11][0] = w[7][0]
  232. w[7][0] = w[3][0]
  233. w[3][0] = a0
  234. a0 = w[15][1]
  235. w[15][1] = w[11][1]
  236. w[11][1] = w[7][1]
  237. w[7][1] = w[3][1]
  238. w[3][1] = a0
  239. for n := uintptr(0); n < 2; n++ {
  240. w0 = w[0][n]
  241. w1 = w[1][n]
  242. w2 = w[2][n]
  243. w3 = w[3][n]
  244. a0 = w0 ^ w1
  245. a1 = w1 ^ w2
  246. a2 = w2 ^ w3
  247. b0 = (((a0&uint64(0x8080808080808080))>>7)*27 ^
  248. ((a0 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  249. b1 = (((a1&uint64(0x8080808080808080))>>7)*27 ^
  250. ((a1 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  251. b2 = (((a2&uint64(0x8080808080808080))>>7)*27 ^
  252. ((a2 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  253. w[0][n] = b0 ^ a1 ^ w3
  254. w[1][n] = b1 ^ w0 ^ a2
  255. w[2][n] = b2 ^ a0 ^ w3
  256. w[3][n] = b0 ^ b1 ^ b2 ^ a0 ^ w2
  257. w0 = w[4][n]
  258. w1 = w[5][n]
  259. w2 = w[6][n]
  260. w3 = w[7][n]
  261. a0 = w0 ^ w1
  262. a1 = w1 ^ w2
  263. a2 = w2 ^ w3
  264. b0 = (((a0&uint64(0x8080808080808080))>>7)*27 ^
  265. ((a0 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  266. b1 = (((a1&uint64(0x8080808080808080))>>7)*27 ^
  267. ((a1 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  268. b2 = (((a2&uint64(0x8080808080808080))>>7)*27 ^
  269. ((a2 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  270. w[4][n] = b0 ^ a1 ^ w3
  271. w[5][n] = b1 ^ w0 ^ a2
  272. w[6][n] = b2 ^ a0 ^ w3
  273. w[7][n] = b0 ^ b1 ^ b2 ^ a0 ^ w2
  274. w0 = w[8][n]
  275. w1 = w[9][n]
  276. w2 = w[10][n]
  277. w3 = w[11][n]
  278. a0 = w0 ^ w1
  279. a1 = w1 ^ w2
  280. a2 = w2 ^ w3
  281. b0 = (((a0&uint64(0x8080808080808080))>>7)*27 ^
  282. ((a0 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  283. b1 = (((a1&uint64(0x8080808080808080))>>7)*27 ^
  284. ((a1 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  285. b2 = (((a2&uint64(0x8080808080808080))>>7)*27 ^
  286. ((a2 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  287. w[8][n] = b0 ^ a1 ^ w3
  288. w[9][n] = b1 ^ w0 ^ a2
  289. w[10][n] = b2 ^ a0 ^ w3
  290. w[11][n] = b0 ^ b1 ^ b2 ^ a0 ^ w2
  291. w0 = w[12][n]
  292. w1 = w[13][n]
  293. w2 = w[14][n]
  294. w3 = w[15][n]
  295. a0 = w0 ^ w1
  296. a1 = w1 ^ w2
  297. a2 = w2 ^ w3
  298. b0 = (((a0&uint64(0x8080808080808080))>>7)*27 ^
  299. ((a0 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  300. b1 = (((a1&uint64(0x8080808080808080))>>7)*27 ^
  301. ((a1 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  302. b2 = (((a2&uint64(0x8080808080808080))>>7)*27 ^
  303. ((a2 & uint64(0x7F7F7F7F7F7F7F7F)) << 1))
  304. w[12][n] = b0 ^ a1 ^ w3
  305. w[13][n] = b1 ^ w0 ^ a2
  306. w[14][n] = b2 ^ a0 ^ w3
  307. w[15][n] = b0 ^ b1 ^ b2 ^ a0 ^ w2
  308. }
  309. }
  310. h := ref.h[:]
  311. for x := uintptr(0); x < 8; x++ {
  312. for y := uintptr(0); y < 2; y++ {
  313. h[x][y] ^= decUInt64le(ref.b[(((x*2)+y)*8):]) ^ w[x][y] ^ w[x+8][y]
  314. }
  315. }
  316. }
  317. func decUInt64le(src []byte) uint64 {
  318. return (uint64(src[0]) |
  319. uint64(src[1])<<8 |
  320. uint64(src[2])<<16 |
  321. uint64(src[3])<<24 |
  322. uint64(src[4])<<32 |
  323. uint64(src[5])<<40 |
  324. uint64(src[6])<<48 |
  325. uint64(src[7])<<56)
  326. }
  327. func encUInt16le(dst []byte, src uint16) {
  328. dst[0] = uint8(src)
  329. dst[1] = uint8(src >> 8)
  330. }
  331. func encUInt32le(dst []uint8, src uint32) {
  332. dst[0] = uint8(src)
  333. dst[1] = uint8(src >> 8)
  334. dst[2] = uint8(src >> 16)
  335. dst[3] = uint8(src >> 24)
  336. }
  337. func encUInt64le(dst []byte, src uint64) {
  338. dst[0] = uint8(src)
  339. dst[1] = uint8(src >> 8)
  340. dst[2] = uint8(src >> 16)
  341. dst[3] = uint8(src >> 24)
  342. dst[4] = uint8(src >> 32)
  343. dst[5] = uint8(src >> 40)
  344. dst[6] = uint8(src >> 48)
  345. dst[7] = uint8(src >> 56)
  346. }