github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/crypto/aes/cipher_asm.go (about) 1 // Copyright 2012 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 // +build amd64 arm64 6 7 package aes 8 9 import ( 10 "crypto/cipher" 11 "crypto/internal/subtle" 12 "internal/cpu" 13 ) 14 15 // defined in asm_*.s 16 17 //go:noescape 18 func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) 19 20 //go:noescape 21 func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) 22 23 //go:noescape 24 func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32) 25 26 type aesCipherAsm struct { 27 aesCipher 28 } 29 30 var supportsAES = cpu.X86.HasAES || cpu.ARM64.HasAES 31 var supportsGFMUL = cpu.X86.HasPCLMULQDQ || cpu.ARM64.HasPMULL 32 33 func newCipher(key []byte) (cipher.Block, error) { 34 if !supportsAES { 35 return newCipherGeneric(key) 36 } 37 n := len(key) + 28 38 c := aesCipherAsm{aesCipher{make([]uint32, n), make([]uint32, n)}} 39 var rounds int 40 switch len(key) { 41 case 128 / 8: 42 rounds = 10 43 case 192 / 8: 44 rounds = 12 45 case 256 / 8: 46 rounds = 14 47 } 48 49 expandKeyAsm(rounds, &key[0], &c.enc[0], &c.dec[0]) 50 if supportsAES && supportsGFMUL { 51 return &aesCipherGCM{c}, nil 52 } 53 return &c, nil 54 } 55 56 func (c *aesCipherAsm) BlockSize() int { return BlockSize } 57 58 func (c *aesCipherAsm) Encrypt(dst, src []byte) { 59 if len(src) < BlockSize { 60 panic("crypto/aes: input not full block") 61 } 62 if len(dst) < BlockSize { 63 panic("crypto/aes: output not full block") 64 } 65 if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { 66 panic("crypto/aes: invalid buffer overlap") 67 } 68 encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0]) 69 } 70 71 func (c *aesCipherAsm) Decrypt(dst, src []byte) { 72 if len(src) < BlockSize { 73 panic("crypto/aes: input not full block") 74 } 75 if len(dst) < BlockSize { 76 panic("crypto/aes: output not full block") 77 } 78 if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { 79 panic("crypto/aes: invalid buffer overlap") 80 } 81 decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0]) 82 } 83 84 // expandKey is used by BenchmarkExpand to ensure that the asm implementation 85 // of key expansion is used for the benchmark when it is available. 86 func expandKey(key []byte, enc, dec []uint32) { 87 if supportsAES { 88 rounds := 10 // rounds needed for AES128 89 switch len(key) { 90 case 192 / 8: 91 rounds = 12 92 case 256 / 8: 93 rounds = 14 94 } 95 expandKeyAsm(rounds, &key[0], &enc[0], &dec[0]) 96 } else { 97 expandKeyGo(key, enc, dec) 98 } 99 }