| // Copyright 2018 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found src the LICENSE file. |
| |
| package chacha20 |
| |
| import "runtime" |
| |
| // Platforms that have fast unaligned 32-bit little endian accesses. |
| const unaligned = runtime.GOARCH == "386" || |
| runtime.GOARCH == "amd64" || |
| runtime.GOARCH == "arm64" || |
| runtime.GOARCH == "ppc64le" || |
| runtime.GOARCH == "s390x" |
| |
| // addXor reads a little endian uint32 from src, XORs it with (a + b) and |
| // places the result in little endian byte order in dst. |
| func addXor(dst, src []byte, a, b uint32) { |
| _, _ = src[3], dst[3] // bounds check elimination hint |
| if unaligned { |
| // The compiler should optimize this code into |
| // 32-bit unaligned little endian loads and stores. |
| // TODO: delete once the compiler does a reliably |
| // good job with the generic code below. |
| // See issue #25111 for more details. |
| v := uint32(src[0]) |
| v |= uint32(src[1]) << 8 |
| v |= uint32(src[2]) << 16 |
| v |= uint32(src[3]) << 24 |
| v ^= a + b |
| dst[0] = byte(v) |
| dst[1] = byte(v >> 8) |
| dst[2] = byte(v >> 16) |
| dst[3] = byte(v >> 24) |
| } else { |
| a += b |
| dst[0] = src[0] ^ byte(a) |
| dst[1] = src[1] ^ byte(a>>8) |
| dst[2] = src[2] ^ byte(a>>16) |
| dst[3] = src[3] ^ byte(a>>24) |
| } |
| } |