aes_asm.mx raw
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 //go:build (amd64 || arm64 || ppc64 || ppc64le) && !purego
6
7 package aes
8
9 import (
10 "crypto/internal/fips140deps/cpu"
11 "crypto/internal/fips140deps/godebug"
12 "crypto/internal/impl"
13 )
14
15 //go:noescape
16 func encryptBlockAsm(nr int, xk *uint32, dst, src *byte)
17
18 //go:noescape
19 func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
20
21 //go:noescape
22 func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32)
23
24 var supportsAES = cpu.X86HasAES && cpu.X86HasSSE41 && cpu.X86HasSSSE3 ||
25 cpu.ARM64HasAES || cpu.PPC64 || cpu.PPC64le
26
27 func init() {
28 if cpu.AMD64 {
29 impl.Register("aes", "AES-NI", &supportsAES)
30 }
31 if cpu.ARM64 {
32 impl.Register("aes", "Armv8.0", &supportsAES)
33 }
34 if cpu.PPC64 || cpu.PPC64le {
35 // The POWER architecture doesn't have a way to turn off AES support
36 // at runtime with GODEBUG=cpu.something=off, so introduce a new GODEBUG
37 // knob for that. It's intentionally only checked at init() time, to
38 // avoid the performance overhead of checking it every time.
39 if godebug.Value("#ppc64aes") == "off" {
40 supportsAES = false
41 }
42 impl.Register("aes", "POWER8", &supportsAES)
43 }
44 }
45
46 // checkGenericIsExpected is called by the variable-time implementation to make
47 // sure it is not used when hardware support is available. It shouldn't happen,
48 // but this way it's more evidently correct.
49 func checkGenericIsExpected() {
50 if supportsAES {
51 panic("crypto/aes: internal error: using generic implementation despite hardware support")
52 }
53 }
54
55 type block struct {
56 blockExpanded
57 }
58
59 func newBlock(c *Block, key []byte) *Block {
60 switch len(key) {
61 case aes128KeySize:
62 c.rounds = aes128Rounds
63 case aes192KeySize:
64 c.rounds = aes192Rounds
65 case aes256KeySize:
66 c.rounds = aes256Rounds
67 }
68 if supportsAES {
69 expandKeyAsm(c.rounds, &key[0], &c.enc[0], &c.dec[0])
70 } else {
71 expandKeyGeneric(&c.blockExpanded, key)
72 }
73 return c
74 }
75
76 // EncryptionKeySchedule is used from the GCM implementation to access the
77 // precomputed AES key schedule, to pass to the assembly implementation.
78 func EncryptionKeySchedule(c *Block) []uint32 {
79 return c.enc[:c.roundKeysSize()]
80 }
81
82 func encryptBlock(c *Block, dst, src []byte) {
83 if supportsAES {
84 encryptBlockAsm(c.rounds, &c.enc[0], &dst[0], &src[0])
85 } else {
86 encryptBlockGeneric(&c.blockExpanded, dst, src)
87 }
88 }
89
90 func decryptBlock(c *Block, dst, src []byte) {
91 if supportsAES {
92 decryptBlockAsm(c.rounds, &c.dec[0], &dst[0], &src[0])
93 } else {
94 decryptBlockGeneric(&c.blockExpanded, dst, src)
95 }
96 }
97