sha256.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. * Minio Cloud Storage, (C) 2016 Minio, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package sha256
  17. import (
  18. "crypto/sha256"
  19. "encoding/binary"
  20. "hash"
  21. "runtime"
  22. )
  23. // Size - The size of a SHA256 checksum in bytes.
  24. const Size = 32
  25. // BlockSize - The blocksize of SHA256 in bytes.
  26. const BlockSize = 64
  27. const (
  28. chunk = BlockSize
  29. init0 = 0x6A09E667
  30. init1 = 0xBB67AE85
  31. init2 = 0x3C6EF372
  32. init3 = 0xA54FF53A
  33. init4 = 0x510E527F
  34. init5 = 0x9B05688C
  35. init6 = 0x1F83D9AB
  36. init7 = 0x5BE0CD19
  37. )
  38. // digest represents the partial evaluation of a checksum.
  39. type digest struct {
  40. h [8]uint32
  41. x [chunk]byte
  42. nx int
  43. len uint64
  44. }
  45. // Reset digest back to default
  46. func (d *digest) Reset() {
  47. d.h[0] = init0
  48. d.h[1] = init1
  49. d.h[2] = init2
  50. d.h[3] = init3
  51. d.h[4] = init4
  52. d.h[5] = init5
  53. d.h[6] = init6
  54. d.h[7] = init7
  55. d.nx = 0
  56. d.len = 0
  57. }
  58. type blockfuncType int
  59. const (
  60. blockfuncGeneric blockfuncType = iota
  61. blockfuncAvx512 blockfuncType = iota
  62. blockfuncAvx2 blockfuncType = iota
  63. blockfuncAvx blockfuncType = iota
  64. blockfuncSsse blockfuncType = iota
  65. blockfuncSha blockfuncType = iota
  66. blockfuncArm blockfuncType = iota
  67. )
  68. var blockfunc blockfuncType
  69. func init() {
  70. is386bit := runtime.GOARCH == "386"
  71. isARM := runtime.GOARCH == "arm"
  72. switch {
  73. case is386bit || isARM:
  74. blockfunc = blockfuncGeneric
  75. case sha && ssse3 && sse41:
  76. blockfunc = blockfuncSha
  77. case avx2:
  78. blockfunc = blockfuncAvx2
  79. case avx:
  80. blockfunc = blockfuncAvx
  81. case ssse3:
  82. blockfunc = blockfuncSsse
  83. case armSha:
  84. blockfunc = blockfuncArm
  85. default:
  86. blockfunc = blockfuncGeneric
  87. }
  88. }
  89. // New returns a new hash.Hash computing the SHA256 checksum.
  90. func New() hash.Hash {
  91. if blockfunc != blockfuncGeneric {
  92. d := new(digest)
  93. d.Reset()
  94. return d
  95. }
  96. // Fallback to the standard golang implementation
  97. // if no features were found.
  98. return sha256.New()
  99. }
  100. // Sum256 - single caller sha256 helper
  101. func Sum256(data []byte) (result [Size]byte) {
  102. var d digest
  103. d.Reset()
  104. d.Write(data)
  105. result = d.checkSum()
  106. return
  107. }
  108. // Return size of checksum
  109. func (d *digest) Size() int { return Size }
  110. // Return blocksize of checksum
  111. func (d *digest) BlockSize() int { return BlockSize }
  112. // Write to digest
  113. func (d *digest) Write(p []byte) (nn int, err error) {
  114. nn = len(p)
  115. d.len += uint64(nn)
  116. if d.nx > 0 {
  117. n := copy(d.x[d.nx:], p)
  118. d.nx += n
  119. if d.nx == chunk {
  120. block(d, d.x[:])
  121. d.nx = 0
  122. }
  123. p = p[n:]
  124. }
  125. if len(p) >= chunk {
  126. n := len(p) &^ (chunk - 1)
  127. block(d, p[:n])
  128. p = p[n:]
  129. }
  130. if len(p) > 0 {
  131. d.nx = copy(d.x[:], p)
  132. }
  133. return
  134. }
  135. // Return sha256 sum in bytes
  136. func (d *digest) Sum(in []byte) []byte {
  137. // Make a copy of d0 so that caller can keep writing and summing.
  138. d0 := *d
  139. hash := d0.checkSum()
  140. return append(in, hash[:]...)
  141. }
  142. // Intermediate checksum function
  143. func (d *digest) checkSum() (digest [Size]byte) {
  144. n := d.nx
  145. var k [64]byte
  146. copy(k[:], d.x[:n])
  147. k[n] = 0x80
  148. if n >= 56 {
  149. block(d, k[:])
  150. // clear block buffer - go compiles this to optimal 1x xorps + 4x movups
  151. // unfortunately expressing this more succinctly results in much worse code
  152. k[0] = 0
  153. k[1] = 0
  154. k[2] = 0
  155. k[3] = 0
  156. k[4] = 0
  157. k[5] = 0
  158. k[6] = 0
  159. k[7] = 0
  160. k[8] = 0
  161. k[9] = 0
  162. k[10] = 0
  163. k[11] = 0
  164. k[12] = 0
  165. k[13] = 0
  166. k[14] = 0
  167. k[15] = 0
  168. k[16] = 0
  169. k[17] = 0
  170. k[18] = 0
  171. k[19] = 0
  172. k[20] = 0
  173. k[21] = 0
  174. k[22] = 0
  175. k[23] = 0
  176. k[24] = 0
  177. k[25] = 0
  178. k[26] = 0
  179. k[27] = 0
  180. k[28] = 0
  181. k[29] = 0
  182. k[30] = 0
  183. k[31] = 0
  184. k[32] = 0
  185. k[33] = 0
  186. k[34] = 0
  187. k[35] = 0
  188. k[36] = 0
  189. k[37] = 0
  190. k[38] = 0
  191. k[39] = 0
  192. k[40] = 0
  193. k[41] = 0
  194. k[42] = 0
  195. k[43] = 0
  196. k[44] = 0
  197. k[45] = 0
  198. k[46] = 0
  199. k[47] = 0
  200. k[48] = 0
  201. k[49] = 0
  202. k[50] = 0
  203. k[51] = 0
  204. k[52] = 0
  205. k[53] = 0
  206. k[54] = 0
  207. k[55] = 0
  208. k[56] = 0
  209. k[57] = 0
  210. k[58] = 0
  211. k[59] = 0
  212. k[60] = 0
  213. k[61] = 0
  214. k[62] = 0
  215. k[63] = 0
  216. }
  217. binary.BigEndian.PutUint64(k[56:64], uint64(d.len)<<3)
  218. block(d, k[:])
  219. {
  220. const i = 0
  221. binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
  222. }
  223. {
  224. const i = 1
  225. binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
  226. }
  227. {
  228. const i = 2
  229. binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
  230. }
  231. {
  232. const i = 3
  233. binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
  234. }
  235. {
  236. const i = 4
  237. binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
  238. }
  239. {
  240. const i = 5
  241. binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
  242. }
  243. {
  244. const i = 6
  245. binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
  246. }
  247. {
  248. const i = 7
  249. binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
  250. }
  251. return
  252. }
  253. func block(dig *digest, p []byte) {
  254. if blockfunc == blockfuncSha {
  255. blockShaGo(dig, p)
  256. } else if blockfunc == blockfuncAvx2 {
  257. blockAvx2Go(dig, p)
  258. } else if blockfunc == blockfuncAvx {
  259. blockAvxGo(dig, p)
  260. } else if blockfunc == blockfuncSsse {
  261. blockSsseGo(dig, p)
  262. } else if blockfunc == blockfuncArm {
  263. blockArmGo(dig, p)
  264. } else if blockfunc == blockfuncGeneric {
  265. blockGeneric(dig, p)
  266. }
  267. }
  268. func blockGeneric(dig *digest, p []byte) {
  269. var w [64]uint32
  270. h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
  271. for len(p) >= chunk {
  272. // Can interlace the computation of w with the
  273. // rounds below if needed for speed.
  274. for i := 0; i < 16; i++ {
  275. j := i * 4
  276. w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
  277. }
  278. for i := 16; i < 64; i++ {
  279. v1 := w[i-2]
  280. t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10)
  281. v2 := w[i-15]
  282. t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3)
  283. w[i] = t1 + w[i-7] + t2 + w[i-16]
  284. }
  285. a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
  286. for i := 0; i < 64; i++ {
  287. t1 := h + ((e>>6 | e<<(32-6)) ^ (e>>11 | e<<(32-11)) ^ (e>>25 | e<<(32-25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i]
  288. t2 := ((a>>2 | a<<(32-2)) ^ (a>>13 | a<<(32-13)) ^ (a>>22 | a<<(32-22))) + ((a & b) ^ (a & c) ^ (b & c))
  289. h = g
  290. g = f
  291. f = e
  292. e = d + t1
  293. d = c
  294. c = b
  295. b = a
  296. a = t1 + t2
  297. }
  298. h0 += a
  299. h1 += b
  300. h2 += c
  301. h3 += d
  302. h4 += e
  303. h5 += f
  304. h6 += g
  305. h7 += h
  306. p = p[chunk:]
  307. }
  308. dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
  309. }
  310. var _K = []uint32{
  311. 0x428a2f98,
  312. 0x71374491,
  313. 0xb5c0fbcf,
  314. 0xe9b5dba5,
  315. 0x3956c25b,
  316. 0x59f111f1,
  317. 0x923f82a4,
  318. 0xab1c5ed5,
  319. 0xd807aa98,
  320. 0x12835b01,
  321. 0x243185be,
  322. 0x550c7dc3,
  323. 0x72be5d74,
  324. 0x80deb1fe,
  325. 0x9bdc06a7,
  326. 0xc19bf174,
  327. 0xe49b69c1,
  328. 0xefbe4786,
  329. 0x0fc19dc6,
  330. 0x240ca1cc,
  331. 0x2de92c6f,
  332. 0x4a7484aa,
  333. 0x5cb0a9dc,
  334. 0x76f988da,
  335. 0x983e5152,
  336. 0xa831c66d,
  337. 0xb00327c8,
  338. 0xbf597fc7,
  339. 0xc6e00bf3,
  340. 0xd5a79147,
  341. 0x06ca6351,
  342. 0x14292967,
  343. 0x27b70a85,
  344. 0x2e1b2138,
  345. 0x4d2c6dfc,
  346. 0x53380d13,
  347. 0x650a7354,
  348. 0x766a0abb,
  349. 0x81c2c92e,
  350. 0x92722c85,
  351. 0xa2bfe8a1,
  352. 0xa81a664b,
  353. 0xc24b8b70,
  354. 0xc76c51a3,
  355. 0xd192e819,
  356. 0xd6990624,
  357. 0xf40e3585,
  358. 0x106aa070,
  359. 0x19a4c116,
  360. 0x1e376c08,
  361. 0x2748774c,
  362. 0x34b0bcb5,
  363. 0x391c0cb3,
  364. 0x4ed8aa4a,
  365. 0x5b9cca4f,
  366. 0x682e6ff3,
  367. 0x748f82ee,
  368. 0x78a5636f,
  369. 0x84c87814,
  370. 0x8cc70208,
  371. 0x90befffa,
  372. 0xa4506ceb,
  373. 0xbef9a3f7,
  374. 0xc67178f2,
  375. }