sha3/xor_unaligned.go

72 lines
2 KiB
Go

// 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"