github.com/mangodowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/crypto/cipher/xor.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package cipher
     6  
     7  import (
     8  	"runtime"
     9  	"unsafe"
    10  )
    11  
    12  const wordSize = int(unsafe.Sizeof(uintptr(0)))
    13  const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"
    14  
    15  // fastXORBytes xors in bulk. It only works on architectures that
    16  // support unaligned read/writes.
    17  func fastXORBytes(dst, a, b []byte) int {
    18  	n := len(a)
    19  	if len(b) < n {
    20  		n = len(b)
    21  	}
    22  
    23  	w := n / wordSize
    24  	if w > 0 {
    25  		dw := *(*[]uintptr)(unsafe.Pointer(&dst))
    26  		aw := *(*[]uintptr)(unsafe.Pointer(&a))
    27  		bw := *(*[]uintptr)(unsafe.Pointer(&b))
    28  		for i := 0; i < w; i++ {
    29  			dw[i] = aw[i] ^ bw[i]
    30  		}
    31  	}
    32  
    33  	for i := (n - n%wordSize); i < n; i++ {
    34  		dst[i] = a[i] ^ b[i]
    35  	}
    36  
    37  	return n
    38  }
    39  
    40  func safeXORBytes(dst, a, b []byte) int {
    41  	n := len(a)
    42  	if len(b) < n {
    43  		n = len(b)
    44  	}
    45  	for i := 0; i < n; i++ {
    46  		dst[i] = a[i] ^ b[i]
    47  	}
    48  	return n
    49  }
    50  
    51  // xorBytes xors the bytes in a and b. The destination is assumed to have enough
    52  // space. Returns the number of bytes xor'd.
    53  func xorBytes(dst, a, b []byte) int {
    54  	if supportsUnaligned {
    55  		return fastXORBytes(dst, a, b)
    56  	} else {
    57  		// TODO(hanwen): if (dst, a, b) have common alignment
    58  		// we could still try fastXORBytes. It is not clear
    59  		// how often this happens, and it's only worth it if
    60  		// the block encryption itself is hardware
    61  		// accelerated.
    62  		return safeXORBytes(dst, a, b)
    63  	}
    64  }
    65  
    66  // fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.)
    67  // The arguments are assumed to be of equal length.
    68  func fastXORWords(dst, a, b []byte) {
    69  	dw := *(*[]uintptr)(unsafe.Pointer(&dst))
    70  	aw := *(*[]uintptr)(unsafe.Pointer(&a))
    71  	bw := *(*[]uintptr)(unsafe.Pointer(&b))
    72  	n := len(b) / wordSize
    73  	for i := 0; i < n; i++ {
    74  		dw[i] = aw[i] ^ bw[i]
    75  	}
    76  }
    77  
    78  func xorWords(dst, a, b []byte) {
    79  	if supportsUnaligned {
    80  		fastXORWords(dst, a, b)
    81  	} else {
    82  		safeXORBytes(dst, a, b)
    83  	}
    84  }