// Copyright 2012 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. //go:build (amd64 || arm64 || ppc64 || ppc64le) && !purego package aes import ( "crypto/internal/fips140deps/cpu" "crypto/internal/fips140deps/godebug" "crypto/internal/impl" ) //go:noescape func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) //go:noescape func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) //go:noescape func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32) var supportsAES = cpu.X86HasAES && cpu.X86HasSSE41 && cpu.X86HasSSSE3 || cpu.ARM64HasAES || cpu.PPC64 || cpu.PPC64le func init() { if cpu.AMD64 { impl.Register("aes", "AES-NI", &supportsAES) } if cpu.ARM64 { impl.Register("aes", "Armv8.0", &supportsAES) } if cpu.PPC64 || cpu.PPC64le { // The POWER architecture doesn't have a way to turn off AES support // at runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG // knob for that. It's intentionally only checked at init() time, to // avoid the performance overhead of checking it every time. if godebug.Value("#ppc64aes") == "off" { supportsAES = false } impl.Register("aes", "POWER8", &supportsAES) } } // checkGenericIsExpected is called by the variable-time implementation to make // sure it is not used when hardware support is available. It shouldn't happen, // but this way it's more evidently correct. func checkGenericIsExpected() { if supportsAES { panic("crypto/aes: internal error: using generic implementation despite hardware support") } } type block struct { blockExpanded } func newBlock(c *Block, key []byte) *Block { switch len(key) { case aes128KeySize: c.rounds = aes128Rounds case aes192KeySize: c.rounds = aes192Rounds case aes256KeySize: c.rounds = aes256Rounds } if supportsAES { expandKeyAsm(c.rounds, &key[0], &c.enc[0], &c.dec[0]) } else { expandKeyGeneric(&c.blockExpanded, key) } return c } // EncryptionKeySchedule is used from the GCM implementation to access the // precomputed AES key schedule, to pass to the assembly implementation. func EncryptionKeySchedule(c *Block) []uint32 { return c.enc[:c.roundKeysSize()] } func encryptBlock(c *Block, dst, src []byte) { if supportsAES { encryptBlockAsm(c.rounds, &c.enc[0], &dst[0], &src[0]) } else { encryptBlockGeneric(&c.blockExpanded, dst, src) } } func decryptBlock(c *Block, dst, src []byte) { if supportsAES { decryptBlockAsm(c.rounds, &c.dec[0], &dst[0], &src[0]) } else { decryptBlockGeneric(&c.blockExpanded, dst, src) } }