1// Copyright 2009 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256 6// hash algorithms as defined in FIPS 180-4. 7// 8// All the hash.Hash implementations returned by this package also 9// implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to 10// marshal and unmarshal the internal state of the hash. 11package sha512 12 13import ( 14 "crypto" 15 "crypto/internal/boring" 16 "errors" 17 "hash" 18 "internal/byteorder" 19) 20 21func init() { 22 crypto.RegisterHash(crypto.SHA384, New384) 23 crypto.RegisterHash(crypto.SHA512, New) 24 crypto.RegisterHash(crypto.SHA512_224, New512_224) 25 crypto.RegisterHash(crypto.SHA512_256, New512_256) 26} 27 28const ( 29 // Size is the size, in bytes, of a SHA-512 checksum. 30 Size = 64 31 32 // Size224 is the size, in bytes, of a SHA-512/224 checksum. 33 Size224 = 28 34 35 // Size256 is the size, in bytes, of a SHA-512/256 checksum. 36 Size256 = 32 37 38 // Size384 is the size, in bytes, of a SHA-384 checksum. 39 Size384 = 48 40 41 // BlockSize is the block size, in bytes, of the SHA-512/224, 42 // SHA-512/256, SHA-384 and SHA-512 hash functions. 43 BlockSize = 128 44) 45 46const ( 47 chunk = 128 48 init0 = 0x6a09e667f3bcc908 49 init1 = 0xbb67ae8584caa73b 50 init2 = 0x3c6ef372fe94f82b 51 init3 = 0xa54ff53a5f1d36f1 52 init4 = 0x510e527fade682d1 53 init5 = 0x9b05688c2b3e6c1f 54 init6 = 0x1f83d9abfb41bd6b 55 init7 = 0x5be0cd19137e2179 56 init0_224 = 0x8c3d37c819544da2 57 init1_224 = 0x73e1996689dcd4d6 58 init2_224 = 0x1dfab7ae32ff9c82 59 init3_224 = 0x679dd514582f9fcf 60 init4_224 = 0x0f6d2b697bd44da8 61 init5_224 = 0x77e36f7304c48942 62 init6_224 = 0x3f9d85a86a1d36c8 63 init7_224 = 0x1112e6ad91d692a1 64 init0_256 = 0x22312194fc2bf72c 65 init1_256 = 0x9f555fa3c84c64c2 66 init2_256 = 0x2393b86b6f53b151 67 init3_256 = 0x963877195940eabd 68 init4_256 = 0x96283ee2a88effe3 69 init5_256 = 0xbe5e1e2553863992 70 init6_256 = 0x2b0199fc2c85b8aa 71 init7_256 = 0x0eb72ddc81c52ca2 72 init0_384 = 0xcbbb9d5dc1059ed8 73 init1_384 = 0x629a292a367cd507 74 init2_384 = 0x9159015a3070dd17 75 init3_384 = 0x152fecd8f70e5939 76 init4_384 = 0x67332667ffc00b31 77 init5_384 = 0x8eb44a8768581511 78 init6_384 = 0xdb0c2e0d64f98fa7 79 init7_384 = 0x47b5481dbefa4fa4 80) 81 82// digest represents the partial evaluation of a checksum. 83type digest struct { 84 h [8]uint64 85 x [chunk]byte 86 nx int 87 len uint64 88 function crypto.Hash 89} 90 91func (d *digest) Reset() { 92 switch d.function { 93 case crypto.SHA384: 94 d.h[0] = init0_384 95 d.h[1] = init1_384 96 d.h[2] = init2_384 97 d.h[3] = init3_384 98 d.h[4] = init4_384 99 d.h[5] = init5_384 100 d.h[6] = init6_384 101 d.h[7] = init7_384 102 case crypto.SHA512_224: 103 d.h[0] = init0_224 104 d.h[1] = init1_224 105 d.h[2] = init2_224 106 d.h[3] = init3_224 107 d.h[4] = init4_224 108 d.h[5] = init5_224 109 d.h[6] = init6_224 110 d.h[7] = init7_224 111 case crypto.SHA512_256: 112 d.h[0] = init0_256 113 d.h[1] = init1_256 114 d.h[2] = init2_256 115 d.h[3] = init3_256 116 d.h[4] = init4_256 117 d.h[5] = init5_256 118 d.h[6] = init6_256 119 d.h[7] = init7_256 120 default: 121 d.h[0] = init0 122 d.h[1] = init1 123 d.h[2] = init2 124 d.h[3] = init3 125 d.h[4] = init4 126 d.h[5] = init5 127 d.h[6] = init6 128 d.h[7] = init7 129 } 130 d.nx = 0 131 d.len = 0 132} 133 134const ( 135 magic384 = "sha\x04" 136 magic512_224 = "sha\x05" 137 magic512_256 = "sha\x06" 138 magic512 = "sha\x07" 139 marshaledSize = len(magic512) + 8*8 + chunk + 8 140) 141 142func (d *digest) MarshalBinary() ([]byte, error) { 143 b := make([]byte, 0, marshaledSize) 144 switch d.function { 145 case crypto.SHA384: 146 b = append(b, magic384...) 147 case crypto.SHA512_224: 148 b = append(b, magic512_224...) 149 case crypto.SHA512_256: 150 b = append(b, magic512_256...) 151 case crypto.SHA512: 152 b = append(b, magic512...) 153 default: 154 return nil, errors.New("crypto/sha512: invalid hash function") 155 } 156 b = byteorder.BeAppendUint64(b, d.h[0]) 157 b = byteorder.BeAppendUint64(b, d.h[1]) 158 b = byteorder.BeAppendUint64(b, d.h[2]) 159 b = byteorder.BeAppendUint64(b, d.h[3]) 160 b = byteorder.BeAppendUint64(b, d.h[4]) 161 b = byteorder.BeAppendUint64(b, d.h[5]) 162 b = byteorder.BeAppendUint64(b, d.h[6]) 163 b = byteorder.BeAppendUint64(b, d.h[7]) 164 b = append(b, d.x[:d.nx]...) 165 b = b[:len(b)+len(d.x)-d.nx] // already zero 166 b = byteorder.BeAppendUint64(b, d.len) 167 return b, nil 168} 169 170func (d *digest) UnmarshalBinary(b []byte) error { 171 if len(b) < len(magic512) { 172 return errors.New("crypto/sha512: invalid hash state identifier") 173 } 174 switch { 175 case d.function == crypto.SHA384 && string(b[:len(magic384)]) == magic384: 176 case d.function == crypto.SHA512_224 && string(b[:len(magic512_224)]) == magic512_224: 177 case d.function == crypto.SHA512_256 && string(b[:len(magic512_256)]) == magic512_256: 178 case d.function == crypto.SHA512 && string(b[:len(magic512)]) == magic512: 179 default: 180 return errors.New("crypto/sha512: invalid hash state identifier") 181 } 182 if len(b) != marshaledSize { 183 return errors.New("crypto/sha512: invalid hash state size") 184 } 185 b = b[len(magic512):] 186 b, d.h[0] = consumeUint64(b) 187 b, d.h[1] = consumeUint64(b) 188 b, d.h[2] = consumeUint64(b) 189 b, d.h[3] = consumeUint64(b) 190 b, d.h[4] = consumeUint64(b) 191 b, d.h[5] = consumeUint64(b) 192 b, d.h[6] = consumeUint64(b) 193 b, d.h[7] = consumeUint64(b) 194 b = b[copy(d.x[:], b):] 195 b, d.len = consumeUint64(b) 196 d.nx = int(d.len % chunk) 197 return nil 198} 199 200func consumeUint64(b []byte) ([]byte, uint64) { 201 return b[8:], byteorder.BeUint64(b) 202} 203 204// New returns a new hash.Hash computing the SHA-512 checksum. 205func New() hash.Hash { 206 if boring.Enabled { 207 return boring.NewSHA512() 208 } 209 d := &digest{function: crypto.SHA512} 210 d.Reset() 211 return d 212} 213 214// New512_224 returns a new hash.Hash computing the SHA-512/224 checksum. 215func New512_224() hash.Hash { 216 d := &digest{function: crypto.SHA512_224} 217 d.Reset() 218 return d 219} 220 221// New512_256 returns a new hash.Hash computing the SHA-512/256 checksum. 222func New512_256() hash.Hash { 223 d := &digest{function: crypto.SHA512_256} 224 d.Reset() 225 return d 226} 227 228// New384 returns a new hash.Hash computing the SHA-384 checksum. 229func New384() hash.Hash { 230 if boring.Enabled { 231 return boring.NewSHA384() 232 } 233 d := &digest{function: crypto.SHA384} 234 d.Reset() 235 return d 236} 237 238func (d *digest) Size() int { 239 switch d.function { 240 case crypto.SHA512_224: 241 return Size224 242 case crypto.SHA512_256: 243 return Size256 244 case crypto.SHA384: 245 return Size384 246 default: 247 return Size 248 } 249} 250 251func (d *digest) BlockSize() int { return BlockSize } 252 253func (d *digest) Write(p []byte) (nn int, err error) { 254 if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 { 255 boring.Unreachable() 256 } 257 nn = len(p) 258 d.len += uint64(nn) 259 if d.nx > 0 { 260 n := copy(d.x[d.nx:], p) 261 d.nx += n 262 if d.nx == chunk { 263 block(d, d.x[:]) 264 d.nx = 0 265 } 266 p = p[n:] 267 } 268 if len(p) >= chunk { 269 n := len(p) &^ (chunk - 1) 270 block(d, p[:n]) 271 p = p[n:] 272 } 273 if len(p) > 0 { 274 d.nx = copy(d.x[:], p) 275 } 276 return 277} 278 279func (d *digest) Sum(in []byte) []byte { 280 if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 { 281 boring.Unreachable() 282 } 283 // Make a copy of d so that caller can keep writing and summing. 284 d0 := new(digest) 285 *d0 = *d 286 hash := d0.checkSum() 287 switch d0.function { 288 case crypto.SHA384: 289 return append(in, hash[:Size384]...) 290 case crypto.SHA512_224: 291 return append(in, hash[:Size224]...) 292 case crypto.SHA512_256: 293 return append(in, hash[:Size256]...) 294 default: 295 return append(in, hash[:]...) 296 } 297} 298 299func (d *digest) checkSum() [Size]byte { 300 // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. 301 len := d.len 302 var tmp [128 + 16]byte // padding + length buffer 303 tmp[0] = 0x80 304 var t uint64 305 if len%128 < 112 { 306 t = 112 - len%128 307 } else { 308 t = 128 + 112 - len%128 309 } 310 311 // Length in bits. 312 len <<= 3 313 padlen := tmp[:t+16] 314 // Upper 64 bits are always zero, because len variable has type uint64, 315 // and tmp is already zeroed at that index, so we can skip updating it. 316 // byteorder.BePutUint64(padlen[t+0:], 0) 317 byteorder.BePutUint64(padlen[t+8:], len) 318 d.Write(padlen) 319 320 if d.nx != 0 { 321 panic("d.nx != 0") 322 } 323 324 var digest [Size]byte 325 byteorder.BePutUint64(digest[0:], d.h[0]) 326 byteorder.BePutUint64(digest[8:], d.h[1]) 327 byteorder.BePutUint64(digest[16:], d.h[2]) 328 byteorder.BePutUint64(digest[24:], d.h[3]) 329 byteorder.BePutUint64(digest[32:], d.h[4]) 330 byteorder.BePutUint64(digest[40:], d.h[5]) 331 if d.function != crypto.SHA384 { 332 byteorder.BePutUint64(digest[48:], d.h[6]) 333 byteorder.BePutUint64(digest[56:], d.h[7]) 334 } 335 336 return digest 337} 338 339// Sum512 returns the SHA512 checksum of the data. 340func Sum512(data []byte) [Size]byte { 341 if boring.Enabled { 342 return boring.SHA512(data) 343 } 344 d := digest{function: crypto.SHA512} 345 d.Reset() 346 d.Write(data) 347 return d.checkSum() 348} 349 350// Sum384 returns the SHA384 checksum of the data. 351func Sum384(data []byte) [Size384]byte { 352 if boring.Enabled { 353 return boring.SHA384(data) 354 } 355 d := digest{function: crypto.SHA384} 356 d.Reset() 357 d.Write(data) 358 sum := d.checkSum() 359 ap := (*[Size384]byte)(sum[:]) 360 return *ap 361} 362 363// Sum512_224 returns the Sum512/224 checksum of the data. 364func Sum512_224(data []byte) [Size224]byte { 365 d := digest{function: crypto.SHA512_224} 366 d.Reset() 367 d.Write(data) 368 sum := d.checkSum() 369 ap := (*[Size224]byte)(sum[:]) 370 return *ap 371} 372 373// Sum512_256 returns the Sum512/256 checksum of the data. 374func Sum512_256(data []byte) [Size256]byte { 375 d := digest{function: crypto.SHA512_256} 376 d.Reset() 377 d.Write(data) 378 sum := d.checkSum() 379 ap := (*[Size256]byte)(sum[:]) 380 return *ap 381} 382