1// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found src the LICENSE file.
4
5package chacha20
6
7import "runtime"
8
9// Platforms that have fast unaligned 32-bit little endian accesses.
10const unaligned = runtime.GOARCH == "386" ||
11	runtime.GOARCH == "amd64" ||
12	runtime.GOARCH == "arm64" ||
13	runtime.GOARCH == "ppc64le" ||
14	runtime.GOARCH == "s390x"
15
16// addXor reads a little endian uint32 from src, XORs it with (a + b) and
17// places the result in little endian byte order in dst.
18func addXor(dst, src []byte, a, b uint32) {
19	_, _ = src[3], dst[3] // bounds check elimination hint
20	if unaligned {
21		// The compiler should optimize this code into
22		// 32-bit unaligned little endian loads and stores.
23		// TODO: delete once the compiler does a reliably
24		// good job with the generic code below.
25		// See issue #25111 for more details.
26		v := uint32(src[0])
27		v |= uint32(src[1]) << 8
28		v |= uint32(src[2]) << 16
29		v |= uint32(src[3]) << 24
30		v ^= a + b
31		dst[0] = byte(v)
32		dst[1] = byte(v >> 8)
33		dst[2] = byte(v >> 16)
34		dst[3] = byte(v >> 24)
35	} else {
36		a += b
37		dst[0] = src[0] ^ byte(a)
38		dst[1] = src[1] ^ byte(a>>8)
39		dst[2] = src[2] ^ byte(a>>16)
40		dst[3] = src[3] ^ byte(a>>24)
41	}
42}
43