sha256.go raw

   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  
  17  package sha256
  18  
  19  import (
  20  	"crypto/sha256"
  21  	"encoding/binary"
  22  	"errors"
  23  	"hash"
  24  )
  25  
  26  // Size - The size of a SHA256 checksum in bytes.
  27  const Size = 32
  28  
  29  // BlockSize - The blocksize of SHA256 in bytes.
  30  const BlockSize = 64
  31  
  32  const (
  33  	chunk = BlockSize
  34  	init0 = 0x6A09E667
  35  	init1 = 0xBB67AE85
  36  	init2 = 0x3C6EF372
  37  	init3 = 0xA54FF53A
  38  	init4 = 0x510E527F
  39  	init5 = 0x9B05688C
  40  	init6 = 0x1F83D9AB
  41  	init7 = 0x5BE0CD19
  42  )
  43  
  44  // digest represents the partial evaluation of a checksum.
  45  type digest struct {
  46  	h   [8]uint32
  47  	x   [chunk]byte
  48  	nx  int
  49  	len uint64
  50  }
  51  
  52  // Reset digest back to default
  53  func (d *digest) Reset() {
  54  	d.h[0] = init0
  55  	d.h[1] = init1
  56  	d.h[2] = init2
  57  	d.h[3] = init3
  58  	d.h[4] = init4
  59  	d.h[5] = init5
  60  	d.h[6] = init6
  61  	d.h[7] = init7
  62  	d.nx = 0
  63  	d.len = 0
  64  }
  65  
  66  type blockfuncType int
  67  
  68  const (
  69  	blockfuncStdlib blockfuncType = iota
  70  	blockfuncIntelSha
  71  	blockfuncArmSha2
  72  	blockfuncForceGeneric = -1
  73  )
  74  
  75  var blockfunc blockfuncType
  76  
  77  func init() {
  78  	switch {
  79  	case hasIntelSha:
  80  		blockfunc = blockfuncIntelSha
  81  	case hasArmSha2():
  82  		blockfunc = blockfuncArmSha2
  83  	}
  84  }
  85  
  86  // New returns a new hash.Hash computing the SHA256 checksum.
  87  func New() hash.Hash {
  88  	if blockfunc == blockfuncStdlib {
  89  		// Fallback to the standard golang implementation
  90  		// if no features were found.
  91  		return sha256.New()
  92  	}
  93  
  94  	d := new(digest)
  95  	d.Reset()
  96  	return d
  97  }
  98  
  99  // Sum256 - single caller sha256 helper
 100  func Sum256(data []byte) (result [Size]byte) {
 101  	var d digest
 102  	d.Reset()
 103  	d.Write(data)
 104  	result = d.checkSum()
 105  	return
 106  }
 107  
 108  // Return size of checksum
 109  func (d *digest) Size() int { return Size }
 110  
 111  // Return blocksize of checksum
 112  func (d *digest) BlockSize() int { return BlockSize }
 113  
 114  // Write to digest
 115  func (d *digest) Write(p []byte) (nn int, err error) {
 116  	nn = len(p)
 117  	d.len += uint64(nn)
 118  	if d.nx > 0 {
 119  		n := copy(d.x[d.nx:], p)
 120  		d.nx += n
 121  		if d.nx == chunk {
 122  			block(d, d.x[:])
 123  			d.nx = 0
 124  		}
 125  		p = p[n:]
 126  	}
 127  	if len(p) >= chunk {
 128  		n := len(p) &^ (chunk - 1)
 129  		block(d, p[:n])
 130  		p = p[n:]
 131  	}
 132  	if len(p) > 0 {
 133  		d.nx = copy(d.x[:], p)
 134  	}
 135  	return
 136  }
 137  
 138  // Return sha256 sum in bytes
 139  func (d *digest) Sum(in []byte) []byte {
 140  	// Make a copy of d0 so that caller can keep writing and summing.
 141  	d0 := *d
 142  	hash := d0.checkSum()
 143  	return append(in, hash[:]...)
 144  }
 145  
 146  // Intermediate checksum function
 147  func (d *digest) checkSum() (digest [Size]byte) {
 148  	n := d.nx
 149  
 150  	var k [64]byte
 151  	copy(k[:], d.x[:n])
 152  
 153  	k[n] = 0x80
 154  
 155  	if n >= 56 {
 156  		block(d, k[:])
 157  
 158  		// clear block buffer - go compiles this to optimal 1x xorps + 4x movups
 159  		// unfortunately expressing this more succinctly results in much worse code
 160  		k[0] = 0
 161  		k[1] = 0
 162  		k[2] = 0
 163  		k[3] = 0
 164  		k[4] = 0
 165  		k[5] = 0
 166  		k[6] = 0
 167  		k[7] = 0
 168  		k[8] = 0
 169  		k[9] = 0
 170  		k[10] = 0
 171  		k[11] = 0
 172  		k[12] = 0
 173  		k[13] = 0
 174  		k[14] = 0
 175  		k[15] = 0
 176  		k[16] = 0
 177  		k[17] = 0
 178  		k[18] = 0
 179  		k[19] = 0
 180  		k[20] = 0
 181  		k[21] = 0
 182  		k[22] = 0
 183  		k[23] = 0
 184  		k[24] = 0
 185  		k[25] = 0
 186  		k[26] = 0
 187  		k[27] = 0
 188  		k[28] = 0
 189  		k[29] = 0
 190  		k[30] = 0
 191  		k[31] = 0
 192  		k[32] = 0
 193  		k[33] = 0
 194  		k[34] = 0
 195  		k[35] = 0
 196  		k[36] = 0
 197  		k[37] = 0
 198  		k[38] = 0
 199  		k[39] = 0
 200  		k[40] = 0
 201  		k[41] = 0
 202  		k[42] = 0
 203  		k[43] = 0
 204  		k[44] = 0
 205  		k[45] = 0
 206  		k[46] = 0
 207  		k[47] = 0
 208  		k[48] = 0
 209  		k[49] = 0
 210  		k[50] = 0
 211  		k[51] = 0
 212  		k[52] = 0
 213  		k[53] = 0
 214  		k[54] = 0
 215  		k[55] = 0
 216  		k[56] = 0
 217  		k[57] = 0
 218  		k[58] = 0
 219  		k[59] = 0
 220  		k[60] = 0
 221  		k[61] = 0
 222  		k[62] = 0
 223  		k[63] = 0
 224  	}
 225  	binary.BigEndian.PutUint64(k[56:64], uint64(d.len)<<3)
 226  	block(d, k[:])
 227  
 228  	{
 229  		const i = 0
 230  		binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
 231  	}
 232  	{
 233  		const i = 1
 234  		binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
 235  	}
 236  	{
 237  		const i = 2
 238  		binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
 239  	}
 240  	{
 241  		const i = 3
 242  		binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
 243  	}
 244  	{
 245  		const i = 4
 246  		binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
 247  	}
 248  	{
 249  		const i = 5
 250  		binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
 251  	}
 252  	{
 253  		const i = 6
 254  		binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
 255  	}
 256  	{
 257  		const i = 7
 258  		binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
 259  	}
 260  
 261  	return
 262  }
 263  
 264  func block(dig *digest, p []byte) {
 265  	if blockfunc == blockfuncIntelSha {
 266  		blockIntelShaGo(dig, p)
 267  	} else if blockfunc == blockfuncArmSha2 {
 268  		blockArmSha2Go(dig, p)
 269  	} else {
 270  		blockGeneric(dig, p)
 271  	}
 272  }
 273  
 274  func blockGeneric(dig *digest, p []byte) {
 275  	var w [64]uint32
 276  	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]
 277  	for len(p) >= chunk {
 278  		// Can interlace the computation of w with the
 279  		// rounds below if needed for speed.
 280  		for i := 0; i < 16; i++ {
 281  			j := i * 4
 282  			w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
 283  		}
 284  		for i := 16; i < 64; i++ {
 285  			v1 := w[i-2]
 286  			t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10)
 287  			v2 := w[i-15]
 288  			t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3)
 289  			w[i] = t1 + w[i-7] + t2 + w[i-16]
 290  		}
 291  
 292  		a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
 293  
 294  		for i := 0; i < 64; i++ {
 295  			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]
 296  
 297  			t2 := ((a>>2 | a<<(32-2)) ^ (a>>13 | a<<(32-13)) ^ (a>>22 | a<<(32-22))) + ((a & b) ^ (a & c) ^ (b & c))
 298  
 299  			h = g
 300  			g = f
 301  			f = e
 302  			e = d + t1
 303  			d = c
 304  			c = b
 305  			b = a
 306  			a = t1 + t2
 307  		}
 308  
 309  		h0 += a
 310  		h1 += b
 311  		h2 += c
 312  		h3 += d
 313  		h4 += e
 314  		h5 += f
 315  		h6 += g
 316  		h7 += h
 317  
 318  		p = p[chunk:]
 319  	}
 320  
 321  	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
 322  }
 323  
 324  var _K = []uint32{
 325  	0x428a2f98,
 326  	0x71374491,
 327  	0xb5c0fbcf,
 328  	0xe9b5dba5,
 329  	0x3956c25b,
 330  	0x59f111f1,
 331  	0x923f82a4,
 332  	0xab1c5ed5,
 333  	0xd807aa98,
 334  	0x12835b01,
 335  	0x243185be,
 336  	0x550c7dc3,
 337  	0x72be5d74,
 338  	0x80deb1fe,
 339  	0x9bdc06a7,
 340  	0xc19bf174,
 341  	0xe49b69c1,
 342  	0xefbe4786,
 343  	0x0fc19dc6,
 344  	0x240ca1cc,
 345  	0x2de92c6f,
 346  	0x4a7484aa,
 347  	0x5cb0a9dc,
 348  	0x76f988da,
 349  	0x983e5152,
 350  	0xa831c66d,
 351  	0xb00327c8,
 352  	0xbf597fc7,
 353  	0xc6e00bf3,
 354  	0xd5a79147,
 355  	0x06ca6351,
 356  	0x14292967,
 357  	0x27b70a85,
 358  	0x2e1b2138,
 359  	0x4d2c6dfc,
 360  	0x53380d13,
 361  	0x650a7354,
 362  	0x766a0abb,
 363  	0x81c2c92e,
 364  	0x92722c85,
 365  	0xa2bfe8a1,
 366  	0xa81a664b,
 367  	0xc24b8b70,
 368  	0xc76c51a3,
 369  	0xd192e819,
 370  	0xd6990624,
 371  	0xf40e3585,
 372  	0x106aa070,
 373  	0x19a4c116,
 374  	0x1e376c08,
 375  	0x2748774c,
 376  	0x34b0bcb5,
 377  	0x391c0cb3,
 378  	0x4ed8aa4a,
 379  	0x5b9cca4f,
 380  	0x682e6ff3,
 381  	0x748f82ee,
 382  	0x78a5636f,
 383  	0x84c87814,
 384  	0x8cc70208,
 385  	0x90befffa,
 386  	0xa4506ceb,
 387  	0xbef9a3f7,
 388  	0xc67178f2,
 389  }
 390  
 391  const (
 392  	magic256      = "sha\x03"
 393  	marshaledSize = len(magic256) + 8*4 + chunk + 8
 394  )
 395  
 396  func (d *digest) MarshalBinary() ([]byte, error) {
 397  	b := make([]byte, 0, marshaledSize)
 398  	b = append(b, magic256...)
 399  	b = appendUint32(b, d.h[0])
 400  	b = appendUint32(b, d.h[1])
 401  	b = appendUint32(b, d.h[2])
 402  	b = appendUint32(b, d.h[3])
 403  	b = appendUint32(b, d.h[4])
 404  	b = appendUint32(b, d.h[5])
 405  	b = appendUint32(b, d.h[6])
 406  	b = appendUint32(b, d.h[7])
 407  	b = append(b, d.x[:d.nx]...)
 408  	b = b[:len(b)+len(d.x)-d.nx] // already zero
 409  	b = appendUint64(b, d.len)
 410  	return b, nil
 411  }
 412  
 413  func (d *digest) UnmarshalBinary(b []byte) error {
 414  	if len(b) < len(magic256) || string(b[:len(magic256)]) != magic256 {
 415  		return errors.New("crypto/sha256: invalid hash state identifier")
 416  	}
 417  	if len(b) != marshaledSize {
 418  		return errors.New("crypto/sha256: invalid hash state size")
 419  	}
 420  	b = b[len(magic256):]
 421  	b, d.h[0] = consumeUint32(b)
 422  	b, d.h[1] = consumeUint32(b)
 423  	b, d.h[2] = consumeUint32(b)
 424  	b, d.h[3] = consumeUint32(b)
 425  	b, d.h[4] = consumeUint32(b)
 426  	b, d.h[5] = consumeUint32(b)
 427  	b, d.h[6] = consumeUint32(b)
 428  	b, d.h[7] = consumeUint32(b)
 429  	b = b[copy(d.x[:], b):]
 430  	b, d.len = consumeUint64(b)
 431  	d.nx = int(d.len % chunk)
 432  	return nil
 433  }
 434  
 435  func appendUint32(b []byte, v uint32) []byte {
 436  	return append(b,
 437  		byte(v>>24),
 438  		byte(v>>16),
 439  		byte(v>>8),
 440  		byte(v),
 441  	)
 442  }
 443  
 444  func appendUint64(b []byte, v uint64) []byte {
 445  	return append(b,
 446  		byte(v>>56),
 447  		byte(v>>48),
 448  		byte(v>>40),
 449  		byte(v>>32),
 450  		byte(v>>24),
 451  		byte(v>>16),
 452  		byte(v>>8),
 453  		byte(v),
 454  	)
 455  }
 456  
 457  func consumeUint64(b []byte) ([]byte, uint64) {
 458  	_ = b[7]
 459  	x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
 460  		uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
 461  	return b[8:], x
 462  }
 463  
 464  func consumeUint32(b []byte) ([]byte, uint32) {
 465  	_ = b[3]
 466  	x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
 467  	return b[4:], x
 468  }
 469