sha256.go 7.2 KB

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