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.

384 lines
7.3 KiB

  1. // Use of this source code is governed by an ISC
  2. // license that can be found in the LICENSE file.
  3. package shavite
  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 = int(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 [16]uint32
  17. c [4]uint32
  18. b [BlockSize]byte
  19. }
  20. // New returns a new digest to compute a SHAVITE512 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. copy(ref.h[:], kInit[:])
  31. ref.c[0], ref.c[1] = 0, 0
  32. ref.c[2], ref.c[3] = 0, 0
  33. }
  34. // Sum appends the current hash to dst and returns the result
  35. // as a slice. It does not change the underlying hash state.
  36. func (ref *digest) Sum(dst []byte) []byte {
  37. dgt := *ref
  38. hsh := [64]byte{}
  39. dgt.Close(hsh[:], 0, 0)
  40. return append(dst, hsh[:]...)
  41. }
  42. // Write more data to the running hash, never returns an error.
  43. func (ref *digest) Write(src []byte) (int, error) {
  44. sln := uintptr(len(src))
  45. fln := len(src)
  46. ptr := ref.ptr
  47. for sln > 0 {
  48. cln := BlockSize - ptr
  49. if cln > sln {
  50. cln = sln
  51. }
  52. sln -= cln
  53. copy(ref.b[ptr:], src[:cln])
  54. src = src[cln:]
  55. ptr += cln
  56. if ptr == BlockSize {
  57. ref.c[0] += 1024
  58. if ref.c[0] == 0 {
  59. ref.c[1] += 1
  60. if ref.c[1] == 0 {
  61. ref.c[2] += 1
  62. if ref.c[2] == 0 {
  63. ref.c[3] += 1
  64. }
  65. }
  66. }
  67. ref.compress()
  68. ptr = 0
  69. }
  70. }
  71. ref.ptr = ptr
  72. return fln, nil
  73. }
  74. // Close the digest by writing the last bits and storing the hash
  75. // in dst. This prepares the digest for reuse by calling reset. A call
  76. // to Close with a dst that is smaller then HashSize will return an error.
  77. func (ref *digest) Close(dst []byte, bits uint8, bcnt uint8) error {
  78. if ln := len(dst); HashSize > ln {
  79. return fmt.Errorf("Shavite Close: dst min length: %d, got %d", HashSize, ln)
  80. }
  81. var cnt [4]uint32
  82. ptr := ref.ptr
  83. buf := ref.b[:]
  84. ref.c[0] += uint32(ptr<<3) + uint32(bcnt)
  85. cnt[0] = ref.c[0]
  86. cnt[1] = ref.c[1]
  87. cnt[2] = ref.c[2]
  88. cnt[3] = ref.c[3]
  89. z := uint8(0x80) >> bcnt
  90. z = uint8((bits & -z) | z)
  91. if (ptr == 0) && (bcnt == 0) {
  92. buf[0] = 0x80
  93. memset(buf[1:110], 0)
  94. ref.c[0], ref.c[1] = 0, 0
  95. ref.c[2], ref.c[3] = 0, 0
  96. } else if ptr < 110 {
  97. buf[ptr] = z
  98. ptr += 1
  99. memset(buf[ptr:(ptr+(110-ptr))], 0)
  100. } else {
  101. buf[ptr] = z
  102. ptr += 1
  103. memset(buf[ptr:(ptr+(128-ptr))], 0)
  104. ref.compress()
  105. memset(buf[:], 0)
  106. ref.c[0], ref.c[1] = 0, 0
  107. ref.c[2], ref.c[3] = 0, 0
  108. }
  109. encUInt32le(buf[110:], cnt[0])
  110. encUInt32le(buf[114:], cnt[1])
  111. encUInt32le(buf[118:], cnt[2])
  112. encUInt32le(buf[122:], cnt[3])
  113. buf[126] = 0
  114. buf[127] = 2
  115. ref.compress()
  116. for u := uintptr(0); u < 16; u++ {
  117. encUInt32le(dst[(u<<2):], ref.h[u])
  118. }
  119. ref.Reset()
  120. return nil
  121. }
  122. // Size returns the number of bytes required to store the hash.
  123. func (*digest) Size() int {
  124. return HashSize
  125. }
  126. // BlockSize returns the block size of the hash.
  127. func (*digest) BlockSize() int {
  128. return int(BlockSize)
  129. }
  130. ////////////////
  131. func memset(dst []byte, src byte) {
  132. for i := range dst {
  133. dst[i] = src
  134. }
  135. }
  136. func decUInt32le(src []byte) uint32 {
  137. return (uint32(src[0]) |
  138. uint32(src[1])<<8 |
  139. uint32(src[2])<<16 |
  140. uint32(src[3])<<24)
  141. }
  142. func encUInt32le(dst []uint8, src uint32) {
  143. dst[0] = uint8(src)
  144. dst[1] = uint8(src >> 8)
  145. dst[2] = uint8(src >> 16)
  146. dst[3] = uint8(src >> 24)
  147. }
  148. func (ref *digest) compress() {
  149. var p0, p1, p2, p3, p4, p5, p6, p7 uint32
  150. var p8, p9, pA, pB, pC, pD, pE, pF uint32
  151. var t0, t1, t2, t3 uint32
  152. var rk [448]uint32
  153. for i := uintptr(0); i < 32; i++ {
  154. rk[i] = decUInt32le(ref.b[(i * 4):])
  155. //rk[i] = decUInt32be(ref.b[(i * 4):])
  156. }
  157. idx := uintptr(32)
  158. for idx < 448 {
  159. for s := uintptr(0); s < 4; s++ {
  160. t0 = rk[idx-31]
  161. t1 = rk[idx-30]
  162. t2 = rk[idx-29]
  163. t3 = rk[idx-32]
  164. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  165. rk[idx+0] = t0 ^ rk[idx-4]
  166. rk[idx+1] = t1 ^ rk[idx-3]
  167. rk[idx+2] = t2 ^ rk[idx-2]
  168. rk[idx+3] = t3 ^ rk[idx-1]
  169. if idx == 32 {
  170. rk[32] ^= ref.c[0]
  171. rk[33] ^= ref.c[1]
  172. rk[34] ^= ref.c[2]
  173. rk[35] ^= uint32(^ref.c[3])
  174. } else if idx == 440 {
  175. rk[440] ^= ref.c[1]
  176. rk[441] ^= ref.c[0]
  177. rk[442] ^= ref.c[3]
  178. rk[443] ^= uint32(^ref.c[2])
  179. }
  180. idx += 4
  181. t0 = rk[idx-31]
  182. t1 = rk[idx-30]
  183. t2 = rk[idx-29]
  184. t3 = rk[idx-32]
  185. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  186. rk[idx+0] = t0 ^ rk[idx-4]
  187. rk[idx+1] = t1 ^ rk[idx-3]
  188. rk[idx+2] = t2 ^ rk[idx-2]
  189. rk[idx+3] = t3 ^ rk[idx-1]
  190. if idx == 164 {
  191. rk[164] ^= ref.c[3]
  192. rk[165] ^= ref.c[2]
  193. rk[166] ^= ref.c[1]
  194. rk[167] ^= uint32(^ref.c[0])
  195. } else if idx == 316 {
  196. rk[316] ^= ref.c[2]
  197. rk[317] ^= ref.c[3]
  198. rk[318] ^= ref.c[0]
  199. rk[319] ^= uint32(^ref.c[1])
  200. }
  201. idx += 4
  202. }
  203. if idx != 448 {
  204. for s := uintptr(0); s < 8; s++ {
  205. rk[idx+0] = rk[idx-32] ^ rk[idx-7]
  206. rk[idx+1] = rk[idx-31] ^ rk[idx-6]
  207. rk[idx+2] = rk[idx-30] ^ rk[idx-5]
  208. rk[idx+3] = rk[idx-29] ^ rk[idx-4]
  209. idx += 4
  210. }
  211. }
  212. }
  213. p0 = ref.h[0x0]
  214. p1 = ref.h[0x1]
  215. p2 = ref.h[0x2]
  216. p3 = ref.h[0x3]
  217. p4 = ref.h[0x4]
  218. p5 = ref.h[0x5]
  219. p6 = ref.h[0x6]
  220. p7 = ref.h[0x7]
  221. p8 = ref.h[0x8]
  222. p9 = ref.h[0x9]
  223. pA = ref.h[0xA]
  224. pB = ref.h[0xB]
  225. pC = ref.h[0xC]
  226. pD = ref.h[0xD]
  227. pE = ref.h[0xE]
  228. pF = ref.h[0xF]
  229. idx = 0
  230. for r := uint32(0); r < 14; r++ {
  231. t0 = p4 ^ rk[idx+0]
  232. t1 = p5 ^ rk[idx+1]
  233. t2 = p6 ^ rk[idx+2]
  234. t3 = p7 ^ rk[idx+3]
  235. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  236. t0 ^= rk[idx+4]
  237. t1 ^= rk[idx+5]
  238. t2 ^= rk[idx+6]
  239. t3 ^= rk[idx+7]
  240. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  241. t0 ^= rk[idx+8]
  242. t1 ^= rk[idx+9]
  243. t2 ^= rk[idx+10]
  244. t3 ^= rk[idx+11]
  245. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  246. t0 ^= rk[idx+12]
  247. t1 ^= rk[idx+13]
  248. t2 ^= rk[idx+14]
  249. t3 ^= rk[idx+15]
  250. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  251. p0 ^= t0
  252. p1 ^= t1
  253. p2 ^= t2
  254. p3 ^= t3
  255. idx += 16
  256. t0 = pC ^ rk[idx+0]
  257. t1 = pD ^ rk[idx+1]
  258. t2 = pE ^ rk[idx+2]
  259. t3 = pF ^ rk[idx+3]
  260. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  261. t0 ^= rk[idx+4]
  262. t1 ^= rk[idx+5]
  263. t2 ^= rk[idx+6]
  264. t3 ^= rk[idx+7]
  265. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  266. t0 ^= rk[idx+8]
  267. t1 ^= rk[idx+9]
  268. t2 ^= rk[idx+10]
  269. t3 ^= rk[idx+11]
  270. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  271. t0 ^= rk[idx+12]
  272. t1 ^= rk[idx+13]
  273. t2 ^= rk[idx+14]
  274. t3 ^= rk[idx+15]
  275. t0, t1, t2, t3 = aesr.Round32sle(t0, t1, t2, t3)
  276. p8 ^= t0
  277. p9 ^= t1
  278. pA ^= t2
  279. pB ^= t3
  280. idx += 16
  281. t0 = pC
  282. pC = p8
  283. p8 = p4
  284. p4 = p0
  285. p0 = t0
  286. t0 = pD
  287. pD = p9
  288. p9 = p5
  289. p5 = p1
  290. p1 = t0
  291. t0 = pE
  292. pE = pA
  293. pA = p6
  294. p6 = p2
  295. p2 = t0
  296. t0 = pF
  297. pF = pB
  298. pB = p7
  299. p7 = p3
  300. p3 = t0
  301. }
  302. ref.h[0x0] ^= p0
  303. ref.h[0x1] ^= p1
  304. ref.h[0x2] ^= p2
  305. ref.h[0x3] ^= p3
  306. ref.h[0x4] ^= p4
  307. ref.h[0x5] ^= p5
  308. ref.h[0x6] ^= p6
  309. ref.h[0x7] ^= p7
  310. ref.h[0x8] ^= p8
  311. ref.h[0x9] ^= p9
  312. ref.h[0xA] ^= pA
  313. ref.h[0xB] ^= pB
  314. ref.h[0xC] ^= pC
  315. ref.h[0xD] ^= pD
  316. ref.h[0xE] ^= pE
  317. ref.h[0xF] ^= pF
  318. }
  319. ////////////////
  320. var kInit = [16]uint32{
  321. uint32(0x72FCCDD8), uint32(0x79CA4727),
  322. uint32(0x128A077B), uint32(0x40D55AEC),
  323. uint32(0xD1901A06), uint32(0x430AE307),
  324. uint32(0xB29F5CD1), uint32(0xDF07FBFC),
  325. uint32(0x8E45D73D), uint32(0x681AB538),
  326. uint32(0xBDE86578), uint32(0xDD577E47),
  327. uint32(0xE275EADE), uint32(0x502D9FCD),
  328. uint32(0xB9357178), uint32(0x022A4B9A),
  329. }