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