gitlab.com/yawning/chacha20.git@v0.0.0-20230427033715-7877545b1b37/internal/hardware/impl_amd64.go (about) 1 // Copryright (C) 2019 Yawning Angel 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 // +build amd64,!noasm 17 18 package hardware 19 20 import ( 21 "golang.org/x/sys/cpu" 22 23 "gitlab.com/yawning/chacha20.git/internal/api" 24 ) 25 26 //go:noescape 27 func blocksAVX2(s *[api.StateSize]uint32, in, out []byte) 28 29 //go:noescape 30 func hChaChaAVX2(key, nonce []byte, dst *byte) 31 32 //go:noescape 33 func blocksSSSE3(s *[api.StateSize]uint32, in, out []byte) 34 35 //go:noescape 36 func hChaChaSSSE3(key, nonce []byte, dst *byte) 37 38 type implAmd64 struct { 39 name string 40 41 blocksFn func(*[api.StateSize]uint32, []byte, []byte, int) 42 hChaChaFn func([]byte, []byte, *byte) 43 } 44 45 func (impl *implAmd64) Name() string { 46 return impl.name 47 } 48 49 func (impl *implAmd64) Blocks(x *[api.StateSize]uint32, dst, src []byte, nrBlocks int) { 50 impl.blocksFn(x, dst, src, nrBlocks) 51 } 52 53 func (impl *implAmd64) HChaCha(key, nonce []byte, dst []byte) { 54 impl.hChaChaFn(key, nonce, &dst[0]) 55 } 56 57 func blockWrapper(fn func(*[api.StateSize]uint32, []byte, []byte)) func(*[api.StateSize]uint32, []byte, []byte, int) { 58 return func(x *[api.StateSize]uint32, dst, src []byte, nrBlocks int) { 59 sz := nrBlocks * api.BlockSize 60 if src != nil { 61 fn(x, src[:sz], dst[:sz]) 62 } else { 63 // Sub-optimal, but the compiler special cases this to an assembly 64 // optimized runtime.memclrNoHeapPointers, so it's not terrible. 65 for i := range dst[:sz] { 66 dst[i] = 0 67 } 68 fn(x, dst[:sz], dst[:sz]) 69 } 70 } 71 } 72 73 func init() { 74 if cpu.X86.HasAVX2 { 75 hardwareImpls = append(hardwareImpls, &implAmd64{ 76 name: "amd64_avx2", 77 blocksFn: blockWrapper(blocksAVX2), 78 hChaChaFn: hChaChaAVX2, 79 }) 80 } 81 if cpu.X86.HasSSSE3 { 82 hardwareImpls = append(hardwareImpls, &implAmd64{ 83 name: "amd64_ssse3", 84 blocksFn: blockWrapper(blocksSSSE3), 85 hChaChaFn: hChaChaSSSE3, 86 }) 87 } 88 }