github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/morus/hwaccel_amd64.go (about) 1 // hwaccel_amd64.go - AMD64 optimized routines 2 // 3 // To the extent possible under law, Yawning Angel has waived all copyright 4 // and related or neighboring rights to the software, using the Creative 5 // Commons "CC0" public domain dedication. See LICENSE or 6 // <http://creativecommons.org/publicdomain/zero/1.0/> for full details. 7 8 // +build amd64,!gccgo,!noasm,go1.10 9 10 package morus 11 12 import "crypto/subtle" 13 14 //go:noescape 15 func cpuidAmd64(cpuidParams *uint32) 16 17 //go:noescape 18 func xgetbv0Amd64(xcrVec *uint32) 19 20 //go:noescape 21 func aeadEncryptAVX2(c, m, a []byte, nonce, key *byte) 22 23 //go:noescape 24 func aeadDecryptAVX2(m, c, a []byte, nonce, key, tag *byte) 25 26 func supportsAVX2() bool { 27 // https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family 28 const ( 29 osXsaveBit = 1 << 27 30 avx2Bit = 1 << 5 31 ) 32 33 // Check to see if CPUID actually supports the leaf that indicates AVX2. 34 // CPUID.(EAX=0H, ECX=0H) >= 7 35 regs := [4]uint32{0x00} 36 cpuidAmd64(®s[0]) 37 if regs[0] < 7 { 38 return false 39 } 40 41 // Check to see if the OS knows how to save/restore XMM/YMM state. 42 // CPUID.(EAX=01H, ECX=0H):ECX.OSXSAVE[bit 27]==1 43 regs = [4]uint32{0x01} 44 cpuidAmd64(®s[0]) 45 if regs[2]&osXsaveBit == 0 { 46 return false 47 } 48 xcrRegs := [2]uint32{} 49 xgetbv0Amd64(&xcrRegs[0]) 50 if xcrRegs[0]&6 != 6 { 51 return false 52 } 53 54 // Check for AVX2 support. 55 // CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]==1 56 regs = [4]uint32{0x07} 57 cpuidAmd64(®s[0]) 58 return regs[1]&avx2Bit != 0 59 } 60 61 func aeadEncryptYMM(c, m, a, nonce, key []byte) []byte { 62 mLen := len(m) 63 ret, out := sliceForAppend(c, mLen+TagSize) 64 aeadEncryptAVX2(out, m, a, &nonce[0], &key[0]) 65 66 return ret 67 } 68 69 func aeadDecryptYMM(m, c, a, nonce, key []byte) ([]byte, bool) { 70 var tag [TagSize]byte 71 cLen := len(c) 72 73 if cLen < TagSize { 74 return nil, false 75 } 76 77 mLen := cLen - TagSize 78 ret, out := sliceForAppend(m, mLen) 79 aeadDecryptAVX2(out, c[:mLen], a, &nonce[0], &key[0], &tag[0]) 80 81 srcTag := c[mLen:] 82 ok := subtle.ConstantTimeCompare(srcTag, tag[:]) == 1 83 if !ok && mLen > 0 { 84 // Burn decrypted plaintext on auth failure. 85 burnBytes(out[:mLen]) 86 ret = nil 87 } 88 89 return ret, ok 90 } 91 92 var implAVX2 = &hwaccelImpl{ 93 name: "AVX2", 94 aeadEncryptFn: aeadEncryptYMM, 95 aeadDecryptFn: aeadDecryptYMM, 96 } 97 98 func initHardwareAcceleration() { 99 if supportsAVX2() { 100 isHardwareAccelerated = true 101 hardwareAccelImpl = implAVX2 102 } 103 }