xor.mx raw

   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  
   5  package chacha20
   6  
   7  import "runtime"
   8  
   9  // Platforms that have fast unaligned 32-bit little endian accesses.
  10  const 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.
  18  func 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