aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go')
-rw-r--r--vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go127
1 files changed, 127 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
new file mode 100644
index 0000000..7cd7ad8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
@@ -0,0 +1,127 @@
+// Copyright 2016 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.
+
+// +build go1.7,amd64,!gccgo,!appengine
+
+package chacha20poly1305
+
+import "encoding/binary"
+
+//go:noescape
+func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
+
+//go:noescape
+func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
+
+// cpuid is implemented in chacha20poly1305_amd64.s.
+func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
+
+// xgetbv with ecx = 0 is implemented in chacha20poly1305_amd64.s.
+func xgetbv() (eax, edx uint32)
+
+var (
+ useASM bool
+ useAVX2 bool
+)
+
+func init() {
+ detectCPUFeatures()
+}
+
+// detectCPUFeatures is used to detect if cpu instructions
+// used by the functions implemented in assembler in
+// chacha20poly1305_amd64.s are supported.
+func detectCPUFeatures() {
+ maxID, _, _, _ := cpuid(0, 0)
+ if maxID < 1 {
+ return
+ }
+
+ _, _, ecx1, _ := cpuid(1, 0)
+
+ haveSSSE3 := isSet(9, ecx1)
+ useASM = haveSSSE3
+
+ haveOSXSAVE := isSet(27, ecx1)
+
+ osSupportsAVX := false
+ // For XGETBV, OSXSAVE bit is required and sufficient.
+ if haveOSXSAVE {
+ eax, _ := xgetbv()
+ // Check if XMM and YMM registers have OS support.
+ osSupportsAVX = isSet(1, eax) && isSet(2, eax)
+ }
+ haveAVX := isSet(28, ecx1) && osSupportsAVX
+
+ if maxID < 7 {
+ return
+ }
+
+ _, ebx7, _, _ := cpuid(7, 0)
+ haveAVX2 := isSet(5, ebx7) && haveAVX
+ haveBMI2 := isSet(8, ebx7)
+
+ useAVX2 = haveAVX2 && haveBMI2
+}
+
+// isSet checks if bit at bitpos is set in value.
+func isSet(bitpos uint, value uint32) bool {
+ return value&(1<<bitpos) != 0
+}
+
+// setupState writes a ChaCha20 input matrix to state. See
+// https://tools.ietf.org/html/rfc7539#section-2.3.
+func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
+ state[0] = 0x61707865
+ state[1] = 0x3320646e
+ state[2] = 0x79622d32
+ state[3] = 0x6b206574
+
+ state[4] = binary.LittleEndian.Uint32(key[:4])
+ state[5] = binary.LittleEndian.Uint32(key[4:8])
+ state[6] = binary.LittleEndian.Uint32(key[8:12])
+ state[7] = binary.LittleEndian.Uint32(key[12:16])
+ state[8] = binary.LittleEndian.Uint32(key[16:20])
+ state[9] = binary.LittleEndian.Uint32(key[20:24])
+ state[10] = binary.LittleEndian.Uint32(key[24:28])
+ state[11] = binary.LittleEndian.Uint32(key[28:32])
+
+ state[12] = 0
+ state[13] = binary.LittleEndian.Uint32(nonce[:4])
+ state[14] = binary.LittleEndian.Uint32(nonce[4:8])
+ state[15] = binary.LittleEndian.Uint32(nonce[8:12])
+}
+
+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
+ if !useASM {
+ return c.sealGeneric(dst, nonce, plaintext, additionalData)
+ }
+
+ var state [16]uint32
+ setupState(&state, &c.key, nonce)
+
+ ret, out := sliceForAppend(dst, len(plaintext)+16)
+ chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
+ return ret
+}
+
+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+ if !useASM {
+ return c.openGeneric(dst, nonce, ciphertext, additionalData)
+ }
+
+ var state [16]uint32
+ setupState(&state, &c.key, nonce)
+
+ ciphertext = ciphertext[:len(ciphertext)-16]
+ ret, out := sliceForAppend(dst, len(ciphertext))
+ if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
+ for i := range out {
+ out[i] = 0
+ }
+ return nil, errOpen
+ }
+
+ return ret, nil
+}