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.

400 lines
11 KiB

  1. // Use of this source code is governed by an ISC
  2. // license that can be found in the LICENSE file.
  3. package bmw
  4. import (
  5. "fmt"
  6. "gitlab.com/nitya-sattva/go-x11/hash"
  7. )
  8. // HashSize holds the size of a hash in bytes.
  9. const HashSize = uintptr(64)
  10. // BlockSize holds the size of a block in bytes.
  11. const BlockSize = uintptr(128)
  12. ////////////////
  13. type digest struct {
  14. ptr uintptr
  15. cnt uint64
  16. h [16]uint64
  17. b [BlockSize]byte
  18. }
  19. // New returns a new digest compute a BMW512 hash.
  20. func New() hash.Digest {
  21. ref := &digest{}
  22. ref.Reset()
  23. return ref
  24. }
  25. ////////////////
  26. // Reset resets the digest to its initial state.
  27. func (ref *digest) Reset() {
  28. ref.ptr = 0
  29. ref.cnt = 0
  30. copy(ref.h[:], kInit[:])
  31. }
  32. // Sum appends the current hash to dst and returns the result
  33. // as a slice. It does not change the underlying hash state.
  34. func (ref *digest) Sum(dst []byte) []byte {
  35. dgt := *ref
  36. hsh := [64]byte{}
  37. dgt.Close(hsh[:], 0, 0)
  38. return append(dst, hsh[:]...)
  39. }
  40. // Write more data to the running hash, never returns an error.
  41. func (ref *digest) Write(src []byte) (int, error) {
  42. sln := uintptr(len(src))
  43. fln := len(src)
  44. ptr := ref.ptr
  45. ht := [16]uint64{}
  46. h1 := ref.h[:]
  47. h2 := ht[:]
  48. ref.cnt += uint64(sln << 3)
  49. for sln > 0 {
  50. cln := BlockSize - ptr
  51. if cln > sln {
  52. cln = sln
  53. }
  54. sln -= cln
  55. copy(ref.b[ptr:], src[:cln])
  56. src = src[cln:]
  57. ptr += cln
  58. if ptr == BlockSize {
  59. compress(ref.b[:], h1, h2)
  60. h1, h2 = h2[:], h1[:]
  61. ptr = 0
  62. }
  63. }
  64. copy(ref.h[:], h1[:])
  65. ref.ptr = ptr
  66. return fln, nil
  67. }
  68. // Close the digest by writing the last bits and storing the hash
  69. // in dst. This prepares the digest for reuse by calling reset. A call
  70. // to Close with a dst that is smaller then HashSize will return an error.
  71. func (ref *digest) Close(dst []byte, bits uint8, bcnt uint8) error {
  72. if ln := len(dst); HashSize > uintptr(ln) {
  73. return fmt.Errorf("Bmw Close: dst min length: %d, got %d", HashSize, ln)
  74. }
  75. buf := ref.b[:]
  76. ptr := ref.ptr + 1
  77. {
  78. off := uint8(0x80) >> bcnt
  79. buf[ref.ptr] = uint8((bits & -off) | off)
  80. }
  81. var h1, h2 [16]uint64
  82. if ptr > (BlockSize - 8) {
  83. memset(buf[ptr:], 0)
  84. compress(buf, ref.h[:], h1[:])
  85. ref.h = h1
  86. ptr = 0
  87. }
  88. memset(buf[ptr:(BlockSize-8)], 0)
  89. encUInt64le(buf[BlockSize-8:], ref.cnt+uint64(bcnt))
  90. compress(buf, ref.h[:], h2[:])
  91. for u := uint8(0); u < 16; u++ {
  92. encUInt64le(buf[(u*8):], h2[u])
  93. }
  94. compress(buf, kFinal[:], h1[:])
  95. for u := uint8(0); u < 8; u++ {
  96. encUInt64le(dst[(u*8):], h1[8+u])
  97. }
  98. ref.Reset()
  99. return nil
  100. }
  101. // Size returns the number of bytes required to store the hash.
  102. func (*digest) Size() int {
  103. return int(HashSize)
  104. }
  105. // BlockSize returns the block size of the hash.
  106. func (*digest) BlockSize() int {
  107. return int(BlockSize)
  108. }
  109. ////////////////
  110. func memset(dst []byte, src byte) {
  111. for i := range dst {
  112. dst[i] = src
  113. }
  114. }
  115. func compress(src []uint8, hv, dh []uint64) {
  116. var xl, xh uint64
  117. mv := [16]uint64{}
  118. qt := [32]uint64{}
  119. mv[0x0] = decUInt64le(src[0:])
  120. mv[0x1] = decUInt64le(src[8:])
  121. mv[0x2] = decUInt64le(src[16:])
  122. mv[0x3] = decUInt64le(src[24:])
  123. mv[0x4] = decUInt64le(src[32:])
  124. mv[0x5] = decUInt64le(src[40:])
  125. mv[0x6] = decUInt64le(src[48:])
  126. mv[0x7] = decUInt64le(src[56:])
  127. mv[0x8] = decUInt64le(src[64:])
  128. mv[0x9] = decUInt64le(src[72:])
  129. mv[0xA] = decUInt64le(src[80:])
  130. mv[0xB] = decUInt64le(src[88:])
  131. mv[0xC] = decUInt64le(src[96:])
  132. mv[0xD] = decUInt64le(src[104:])
  133. mv[0xE] = decUInt64le(src[112:])
  134. mv[0xF] = decUInt64le(src[120:])
  135. {
  136. xv := [16]uint64{}
  137. xv[0x0] = mv[0x0] ^ hv[0x0]
  138. xv[0x1] = mv[0x1] ^ hv[0x1]
  139. xv[0x2] = mv[0x2] ^ hv[0x2]
  140. xv[0x3] = mv[0x3] ^ hv[0x3]
  141. xv[0x4] = mv[0x4] ^ hv[0x4]
  142. xv[0x5] = mv[0x5] ^ hv[0x5]
  143. xv[0x6] = mv[0x6] ^ hv[0x6]
  144. xv[0x7] = mv[0x7] ^ hv[0x7]
  145. xv[0x8] = mv[0x8] ^ hv[0x8]
  146. xv[0x9] = mv[0x9] ^ hv[0x9]
  147. xv[0xA] = mv[0xA] ^ hv[0xA]
  148. xv[0xB] = mv[0xB] ^ hv[0xB]
  149. xv[0xC] = mv[0xC] ^ hv[0xC]
  150. xv[0xD] = mv[0xD] ^ hv[0xD]
  151. xv[0xE] = mv[0xE] ^ hv[0xE]
  152. xv[0xF] = mv[0xF] ^ hv[0xF]
  153. qt[0] = hv[0x1] + shiftBits0(
  154. xv[0x5]-xv[0x7]+xv[0xA]+xv[0xD]+xv[0xE],
  155. )
  156. qt[1] = hv[0x2] + shiftBits1(
  157. xv[0x6]-xv[0x8]+xv[0xB]+xv[0xE]-xv[0xF],
  158. )
  159. qt[2] = hv[0x3] + shiftBits2(
  160. xv[0x0]+xv[0x7]+xv[0x9]-xv[0xC]+xv[0xF],
  161. )
  162. qt[3] = hv[0x4] + shiftBits3(
  163. xv[0x0]-xv[0x1]+xv[0x8]-xv[0xA]+xv[0xD],
  164. )
  165. qt[4] = hv[0x5] + shiftBits4(
  166. xv[0x1]+xv[0x2]+xv[0x9]-xv[0xB]-xv[0xE],
  167. )
  168. qt[5] = hv[0x6] + shiftBits0(
  169. xv[0x3]-xv[0x2]+xv[0xA]-xv[0xC]+xv[0xF],
  170. )
  171. qt[6] = hv[0x7] + shiftBits1(
  172. xv[0x4]-xv[0x0]-xv[0x3]-xv[0xB]+xv[0xD],
  173. )
  174. qt[7] = hv[0x8] + shiftBits2(
  175. xv[0x1]-xv[0x4]-xv[0x5]-xv[0xC]-xv[0xE],
  176. )
  177. qt[8] = hv[0x9] + shiftBits3(
  178. xv[0x2]-xv[0x5]-xv[0x6]+xv[0xD]-xv[0xF],
  179. )
  180. qt[9] = hv[0xA] + shiftBits4(
  181. xv[0x0]-xv[0x3]+xv[0x6]-xv[0x7]+xv[0xE],
  182. )
  183. qt[10] = hv[0xB] + shiftBits0(
  184. xv[0x8]-xv[0x1]-xv[0x4]-xv[0x7]+xv[0xF],
  185. )
  186. qt[11] = hv[0xC] + shiftBits1(
  187. xv[0x8]-xv[0x0]-xv[0x2]-xv[0x5]+xv[0x9],
  188. )
  189. qt[12] = hv[0xD] + shiftBits2(
  190. xv[0x1]+xv[0x3]-xv[0x6]-xv[0x9]+xv[0xA],
  191. )
  192. qt[13] = hv[0xE] + shiftBits3(
  193. xv[0x2]+xv[0x4]+xv[0x7]+xv[0xA]+xv[0xB],
  194. )
  195. qt[14] = hv[0xF] + shiftBits4(
  196. xv[0x3]-xv[0x5]+xv[0x8]-xv[0xB]-xv[0xC],
  197. )
  198. qt[15] = hv[0x0] + shiftBits0(
  199. xv[0xC]-xv[0x4]-xv[0x6]-xv[0x9]+xv[0xD],
  200. )
  201. }
  202. qt[16] = expandOne(16, qt[:], mv[:], hv[:])
  203. qt[17] = expandOne(17, qt[:], mv[:], hv[:])
  204. qt[18] = expandTwo(18, qt[:], mv[:], hv[:])
  205. qt[19] = expandTwo(19, qt[:], mv[:], hv[:])
  206. qt[20] = expandTwo(20, qt[:], mv[:], hv[:])
  207. qt[21] = expandTwo(21, qt[:], mv[:], hv[:])
  208. qt[22] = expandTwo(22, qt[:], mv[:], hv[:])
  209. qt[23] = expandTwo(23, qt[:], mv[:], hv[:])
  210. qt[24] = expandTwo(24, qt[:], mv[:], hv[:])
  211. qt[25] = expandTwo(25, qt[:], mv[:], hv[:])
  212. qt[26] = expandTwo(26, qt[:], mv[:], hv[:])
  213. qt[27] = expandTwo(27, qt[:], mv[:], hv[:])
  214. qt[28] = expandTwo(28, qt[:], mv[:], hv[:])
  215. qt[29] = expandTwo(29, qt[:], mv[:], hv[:])
  216. qt[30] = expandTwo(30, qt[:], mv[:], hv[:])
  217. qt[31] = expandTwo(31, qt[:], mv[:], hv[:])
  218. xl = qt[16] ^ qt[17] ^ qt[18] ^ qt[19] ^ qt[20] ^ qt[21] ^ qt[22] ^ qt[23]
  219. xh = xl ^ qt[24] ^ qt[25] ^ qt[26] ^ qt[27] ^ qt[28] ^ qt[29] ^ qt[30] ^ qt[31]
  220. dh[0x0] = ((xh << 5) ^ (qt[16] >> 5) ^ mv[0x0]) + (xl ^ qt[24] ^ qt[0])
  221. dh[0x1] = ((xh >> 7) ^ (qt[17] << 8) ^ mv[0x1]) + (xl ^ qt[25] ^ qt[1])
  222. dh[0x2] = ((xh >> 5) ^ (qt[18] << 5) ^ mv[0x2]) + (xl ^ qt[26] ^ qt[2])
  223. dh[0x3] = ((xh >> 1) ^ (qt[19] << 5) ^ mv[0x3]) + (xl ^ qt[27] ^ qt[3])
  224. dh[0x4] = ((xh >> 3) ^ (qt[20] << 0) ^ mv[0x4]) + (xl ^ qt[28] ^ qt[4])
  225. dh[0x5] = ((xh << 6) ^ (qt[21] >> 6) ^ mv[0x5]) + (xl ^ qt[29] ^ qt[5])
  226. dh[0x6] = ((xh >> 4) ^ (qt[22] << 6) ^ mv[0x6]) + (xl ^ qt[30] ^ qt[6])
  227. dh[0x7] = ((xh >> 11) ^ (qt[23] << 2) ^ mv[0x7]) + (xl ^ qt[31] ^ qt[7])
  228. dh[0x8] = ((dh[0x4] << 9) | (dh[0x4] >> (64 - 9)))
  229. dh[0x8] += (xh ^ qt[24] ^ mv[0x8]) + ((xl << 8) ^ qt[23] ^ qt[8])
  230. dh[0x9] = ((dh[0x5] << 10) | (dh[0x5] >> (64 - 10)))
  231. dh[0x9] += (xh ^ qt[25] ^ mv[0x9]) + ((xl >> 6) ^ qt[16] ^ qt[9])
  232. dh[0xA] = ((dh[0x6] << 11) | (dh[0x6] >> (64 - 11)))
  233. dh[0xA] += (xh ^ qt[26] ^ mv[0xA]) + ((xl << 6) ^ qt[17] ^ qt[10])
  234. dh[0xB] = ((dh[0x7] << 12) | (dh[0x7] >> (64 - 12)))
  235. dh[0xB] += (xh ^ qt[27] ^ mv[0xB]) + ((xl << 4) ^ qt[18] ^ qt[11])
  236. dh[0xC] = ((dh[0x0] << 13) | (dh[0x0] >> (64 - 13)))
  237. dh[0xC] += (xh ^ qt[28] ^ mv[0xC]) + ((xl >> 3) ^ qt[19] ^ qt[12])
  238. dh[0xD] = ((dh[0x1] << 14) | (dh[0x1] >> (64 - 14)))
  239. dh[0xD] += (xh ^ qt[29] ^ mv[0xD]) + ((xl >> 4) ^ qt[20] ^ qt[13])
  240. dh[0xE] = ((dh[0x2] << 15) | (dh[0x2] >> (64 - 15)))
  241. dh[0xE] += (xh ^ qt[30] ^ mv[0xE]) + ((xl >> 7) ^ qt[21] ^ qt[14])
  242. dh[0xF] = ((dh[0x3] << 16) | (dh[0x3] >> (64 - 16)))
  243. dh[0xF] += (xh ^ qt[31] ^ mv[0xF]) + ((xl >> 2) ^ qt[22] ^ qt[15])
  244. }
  245. func decUInt64le(src []byte) uint64 {
  246. return (uint64(src[0]) |
  247. uint64(src[1])<<8 |
  248. uint64(src[2])<<16 |
  249. uint64(src[3])<<24 |
  250. uint64(src[4])<<32 |
  251. uint64(src[5])<<40 |
  252. uint64(src[6])<<48 |
  253. uint64(src[7])<<56)
  254. }
  255. func encUInt64le(dst []byte, src uint64) {
  256. dst[0] = uint8(src)
  257. dst[1] = uint8(src >> 8)
  258. dst[2] = uint8(src >> 16)
  259. dst[3] = uint8(src >> 24)
  260. dst[4] = uint8(src >> 32)
  261. dst[5] = uint8(src >> 40)
  262. dst[6] = uint8(src >> 48)
  263. dst[7] = uint8(src >> 56)
  264. }
  265. func shiftBits0(x uint64) uint64 {
  266. return ((x >> 1) ^ (x << 3) ^
  267. ((x << 4) | (x >> (64 - 4))) ^
  268. ((x << 37) | (x >> (64 - 37))))
  269. }
  270. func shiftBits1(x uint64) uint64 {
  271. return ((x >> 1) ^ (x << 2) ^
  272. ((x << 13) | (x >> (64 - 13))) ^
  273. ((x << 43) | (x >> (64 - 43))))
  274. }
  275. func shiftBits2(x uint64) uint64 {
  276. return ((x >> 2) ^ (x << 1) ^
  277. ((x << 19) | (x >> (64 - 19))) ^
  278. ((x << 53) | (x >> (64 - 53))))
  279. }
  280. func shiftBits3(x uint64) uint64 {
  281. return ((x >> 2) ^ (x << 2) ^
  282. ((x << 28) | (x >> (64 - 28))) ^
  283. ((x << 59) | (x >> (64 - 59))))
  284. }
  285. func shiftBits4(x uint64) uint64 {
  286. return ((x >> 1) ^ x)
  287. }
  288. func shiftBits5(x uint64) uint64 {
  289. return ((x >> 2) ^ x)
  290. }
  291. func rolBits(idx, off uint8, mv []uint64) uint64 {
  292. x := mv[(idx+off)&15]
  293. n := uint64((idx+off)&15) + 1
  294. return (x << n) | (x >> (64 - n))
  295. }
  296. func addEltBits(idx uint8, mv, hv []uint64) uint64 {
  297. kbt := uint64(idx+16) * uint64(0x0555555555555555)
  298. return ((rolBits(idx, 0, mv) + rolBits(idx, 3, mv) -
  299. rolBits(idx, 10, mv) + kbt) ^ (hv[(idx+7)&15]))
  300. }
  301. func expandOne(idx uint8, qt, mv, hv []uint64) uint64 {
  302. return (shiftBits1(qt[idx-0x10]) + shiftBits2(qt[idx-0x0F]) +
  303. shiftBits3(qt[idx-0x0E]) + shiftBits0(qt[idx-0x0D]) +
  304. shiftBits1(qt[idx-0x0C]) + shiftBits2(qt[idx-0x0B]) +
  305. shiftBits3(qt[idx-0x0A]) + shiftBits0(qt[idx-0x09]) +
  306. shiftBits1(qt[idx-0x08]) + shiftBits2(qt[idx-0x07]) +
  307. shiftBits3(qt[idx-0x06]) + shiftBits0(qt[idx-0x05]) +
  308. shiftBits1(qt[idx-0x04]) + shiftBits2(qt[idx-0x03]) +
  309. shiftBits3(qt[idx-0x02]) + shiftBits0(qt[idx-0x01]) +
  310. addEltBits(uint8(idx-16), mv, hv))
  311. }
  312. func expandTwo(idx uint8, qt, mv, hv []uint64) uint64 {
  313. return (qt[idx-0x10] + ((qt[idx-0x0F] << 5) | (qt[idx-0x0F] >> (64 - 5))) +
  314. qt[idx-0x0E] + ((qt[idx-0x0D] << 11) | (qt[idx-0x0D] >> (64 - 11))) +
  315. qt[idx-0x0C] + ((qt[idx-0x0B] << 27) | (qt[idx-0x0B] >> (64 - 27))) +
  316. qt[idx-0x0A] + ((qt[idx-0x09] << 32) | (qt[idx-0x09] >> (64 - 32))) +
  317. qt[idx-0x08] + ((qt[idx-0x07] << 37) | (qt[idx-0x07] >> (64 - 37))) +
  318. qt[idx-0x06] + ((qt[idx-0x05] << 43) | (qt[idx-0x05] >> (64 - 43))) +
  319. qt[idx-0x04] + ((qt[idx-0x03] << 53) | (qt[idx-0x03] >> (64 - 53))) +
  320. shiftBits4(qt[idx-0x02]) + shiftBits5(qt[idx-0x01]) +
  321. addEltBits(uint8(idx-16), mv, hv))
  322. }
  323. ////////////////
  324. var kInit = [16]uint64{
  325. uint64(0x8081828384858687), uint64(0x88898A8B8C8D8E8F),
  326. uint64(0x9091929394959697), uint64(0x98999A9B9C9D9E9F),
  327. uint64(0xA0A1A2A3A4A5A6A7), uint64(0xA8A9AAABACADAEAF),
  328. uint64(0xB0B1B2B3B4B5B6B7), uint64(0xB8B9BABBBCBDBEBF),
  329. uint64(0xC0C1C2C3C4C5C6C7), uint64(0xC8C9CACBCCCDCECF),
  330. uint64(0xD0D1D2D3D4D5D6D7), uint64(0xD8D9DADBDCDDDEDF),
  331. uint64(0xE0E1E2E3E4E5E6E7), uint64(0xE8E9EAEBECEDEEEF),
  332. uint64(0xF0F1F2F3F4F5F6F7), uint64(0xF8F9FAFBFCFDFEFF),
  333. }
  334. var kFinal = [16]uint64{
  335. uint64(0xaaaaaaaaaaaaaaa0), uint64(0xaaaaaaaaaaaaaaa1),
  336. uint64(0xaaaaaaaaaaaaaaa2), uint64(0xaaaaaaaaaaaaaaa3),
  337. uint64(0xaaaaaaaaaaaaaaa4), uint64(0xaaaaaaaaaaaaaaa5),
  338. uint64(0xaaaaaaaaaaaaaaa6), uint64(0xaaaaaaaaaaaaaaa7),
  339. uint64(0xaaaaaaaaaaaaaaa8), uint64(0xaaaaaaaaaaaaaaa9),
  340. uint64(0xaaaaaaaaaaaaaaaa), uint64(0xaaaaaaaaaaaaaaab),
  341. uint64(0xaaaaaaaaaaaaaaac), uint64(0xaaaaaaaaaaaaaaad),
  342. uint64(0xaaaaaaaaaaaaaaae), uint64(0xaaaaaaaaaaaaaaaf),
  343. }