// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build (amd64 || 386 || ppc64le) && !purego package sha3 import ( "encoding/binary" "unsafe" ) // A storageBuf is an aligned array of maxRate bytes. type storageBuf [maxRate / 8]uint64 func (b *storageBuf) asBytes() *[maxRate]byte { return (*[maxRate]byte)(unsafe.Pointer(b)) } // xorInUnaligned uses unaligned reads and writes to update d.a to contain d.a // XOR buf. func xorInUnaligned(d *HasherState, buf []byte) { n := len(buf) if n >= 72 { d.a[0] ^= binary.LittleEndian.Uint64(buf[8*0:]) d.a[1] ^= binary.LittleEndian.Uint64(buf[8*1:]) d.a[2] ^= binary.LittleEndian.Uint64(buf[8*2:]) d.a[3] ^= binary.LittleEndian.Uint64(buf[8*3:]) d.a[4] ^= binary.LittleEndian.Uint64(buf[8*4:]) d.a[5] ^= binary.LittleEndian.Uint64(buf[8*5:]) d.a[6] ^= binary.LittleEndian.Uint64(buf[8*6:]) d.a[7] ^= binary.LittleEndian.Uint64(buf[8*7:]) d.a[8] ^= binary.LittleEndian.Uint64(buf[8*8:]) } if n >= 104 { d.a[9] ^= binary.LittleEndian.Uint64(buf[8*9:]) d.a[10] ^= binary.LittleEndian.Uint64(buf[8*10:]) d.a[11] ^= binary.LittleEndian.Uint64(buf[8*11:]) d.a[12] ^= binary.LittleEndian.Uint64(buf[8*12:]) } if n >= 136 { d.a[13] ^= binary.LittleEndian.Uint64(buf[8*13:]) d.a[14] ^= binary.LittleEndian.Uint64(buf[8*14:]) d.a[15] ^= binary.LittleEndian.Uint64(buf[8*15:]) d.a[16] ^= binary.LittleEndian.Uint64(buf[8*16:]) } if n >= 144 { d.a[17] ^= binary.LittleEndian.Uint64(buf[8*17:]) } if n >= 168 { d.a[18] ^= binary.LittleEndian.Uint64(buf[8*18:]) d.a[19] ^= binary.LittleEndian.Uint64(buf[8*19:]) d.a[20] ^= binary.LittleEndian.Uint64(buf[8*20:]) } } func copyOutUnaligned(d *HasherState, buf []byte) { ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) copy(buf, ab[:]) } func xorIn(d *HasherState, buf []byte) { xorInUnaligned(d, buf) } var ( copyOut = copyOutUnaligned ) const xorImplementationUnaligned = "unaligned"