iPXE
aesni.c File Reference

AES-NI hardware acceleration. More...

#include <assert.h>
#include <ipxe/cpuid.h>
#include <ipxe/aes.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static void aesni_encrypt (struct cipher_algorithm *cipher __unused, void *ctx, const void *src, void *dst, size_t len)
 Encrypt data.
static void aesni_decrypt (struct cipher_algorithm *cipher __unused, void *ctx, const void *src, void *dst, size_t len)
 Decrypt data.
void aes_accelerate (void)
 Enable hardware acceleration (if supported).

Detailed Description

AES-NI hardware acceleration.

The AES-NI instructions use SSE registers. For the sake of not having to think about the possible consequences across all various runtime environments (BIOS/UEFI/Linux), we choose not to enable "-msse" in CFLAGS for this file. We include ".arch" directives to ensure that the assembler knows that it is permitted to emit the SSE2 and AES-NI instructions, and use a fixed "%xmm0" rather than an "x" constraint (which GCC would consider to be impossible without "-msse").

We rely upon the runtime environment to guarantee that using the "%xmm0" register is a safe operation:

  • For UEFI and Linux, the runtime environment guarantees that SSE registers are saved and restored across any context switch that occurs in the middle of the AES calculation.
  • For BIOS, all C code in iPXE runs with interrupts disabled (unless it enables interrupts itself, e.g. by calling currticks() or by executing an explicit "sti" instruction), which guarantees that no other code will unexpectedly modify the SSE registers in the middle of the AES operation.

We restore the "%xmm0" register after use, to satisfy the constraints of the IA-32 UEFI ABI (which defines all FPU/MMX/SSE registers as callee-saved). This is the most restrictive of the ABIs for which this file can be built:

  • IA32 UEFI requires all XMM registers to be preserved
  • X64 UEFI would allow us to modify any of "%xmm0"-"%xmm5"
  • BIOS via virt_call() would allow us to modify any of "%xmm0"-"%xmm7"
  • System V i386 would allow us to modify any of "%xmm0"-"%xmm7"
  • System V x86_64 would allow us to modify any of "%xmm0"-"%xmm15"

Definition in file aesni.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ aesni_encrypt()

void aesni_encrypt ( struct cipher_algorithm *cipher __unused,
void * ctx,
const void * src,
void * dst,
size_t len )
static

Encrypt data.

Parameters
cipherCipher algorithm
ctxContext
srcData to encrypt
dstBuffer for encrypted data
lenLength of data

Definition at line 84 of file aesni.c.

86 {
87 struct aes_context *aes = aes_context ( ctx );
88 const union aes_matrix *key = aes->encrypt.key;
89 const union aes_matrix *in = src;
90 union aes_matrix *out = dst;
91 union aes_matrix save;
92
93 /* Sanity check */
94 assert ( len == sizeof ( *in ) );
95 assert ( len == sizeof ( *out ) );
96
97 /* Encrypt */
98 asm ( /* Allow SSE2 and AES-NI instructions */
99 ".arch .sse2\n\t"
100 ".arch .aes\n\t"
101 /* Preserve XMM register */
102 "movdqu %%xmm0, %1\n\t"
103 /* Initial round (AddRoundKey) */
104 "movdqu %3, %%xmm0\n\t"
105 "pxor (%0), %%xmm0\n\t"
106 /* Intermediate rounds (ShiftRows, SubBytes, MixColumns,
107 * AddRoundKey).
108 */
109 "cmpb $13, %b4\n\t"
110 "jb 2f\n\t"
111 "je 1f\n\t"
112 /* 15 rounds (13 intermediate rounds) */
113 "aesenc 0x10(%0), %%xmm0\n\t"
114 "aesenc 0x20(%0), %%xmm0\n\t"
115 "lea 0x20(%0), %0\n\t"
116 "\n1:\n\t"
117 /* 13+ rounds (11+ intermediate rounds) */
118 "aesenc 0x10(%0), %%xmm0\n\t"
119 "aesenc 0x20(%0), %%xmm0\n\t"
120 "lea 0x20(%0), %0\n\t"
121 "\n2:\n\t"
122 /* 11+ rounds (9+ intermediate rounds) */
123 "aesenc 0x10(%0), %%xmm0\n\t"
124 "aesenc 0x20(%0), %%xmm0\n\t"
125 "aesenc 0x30(%0), %%xmm0\n\t"
126 "aesenc 0x40(%0), %%xmm0\n\t"
127 "aesenc 0x50(%0), %%xmm0\n\t"
128 "aesenc 0x60(%0), %%xmm0\n\t"
129 "aesenc 0x70(%0), %%xmm0\n\t"
130 "aesenc 0x80(%0), %%xmm0\n\t"
131 "aesenc 0x90(%0), %%xmm0\n\t"
132 /* Final round (ShiftRows, SubBytes, AddRoundKey) */
133 "aesenclast 0xa0(%0), %%xmm0\n\t"
134 "movdqu %%xmm0, %2\n\t"
135 /* Restore XMM register */
136 "movdqu %1, %%xmm0\n\t"
137 : "+r" ( key ), "=m" ( save ), "=m" ( *out )
138 : "m" ( *in ), "rm" ( aes->rounds ), "m" ( aes->encrypt ) );
139}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
__be32 out[4]
Definition CIB_PRM.h:8
__be32 in[4]
Definition CIB_PRM.h:7
union @162305117151260234136356364136041353210355154177 key
static const void * src
Definition string.h:48
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
ring len
Length.
Definition dwmac.h:226
static struct aes_context * aes_context(void *ctx)
Align AES context.
Definition aes.h:55
AES context.
Definition aes.h:37
uint8_t rounds
Number of rounds.
Definition aes.h:43
struct aes_round_keys encrypt
Encryption keys.
Definition aes.h:39
union aes_matrix key[AES_MAX_ROUNDS]
Round keys.
Definition aes.h:33
AES matrix.
Definition aes.h:23

References __unused, aes_context(), assert, ctx, aes_context::encrypt, in, aes_round_keys::key, key, len, out, aes_context::rounds, and src.

Referenced by aes_accelerate().

◆ aesni_decrypt()

void aesni_decrypt ( struct cipher_algorithm *cipher __unused,
void * ctx,
const void * src,
void * dst,
size_t len )
static

Decrypt data.

Parameters
cipherCipher algorithm
ctxContext
srcData to encrypt
dstBuffer for encrypted data
lenLength of data

Definition at line 150 of file aesni.c.

152 {
153 struct aes_context *aes = aes_context ( ctx );
154 const union aes_matrix *key = aes->decrypt.key;
155 const union aes_matrix *in = src;
156 union aes_matrix *out = dst;
157 union aes_matrix save;
158
159 /* Sanity check */
160 assert ( len == sizeof ( *in ) );
161 assert ( len == sizeof ( *out ) );
162
163 /* Decrypt */
164 asm ( /* Allow SSE2 and AES-NI instructions */
165 ".arch .sse2\n\t"
166 ".arch .aes\n\t"
167 /* Preserve XMM register */
168 "movdqu %%xmm0, %1\n\t"
169 /* Initial round (AddRoundKey) */
170 "movdqu %3, %%xmm0\n\t"
171 "pxor (%0), %%xmm0\n\t"
172 /* Intermediate rounds (InvShiftRows, InvSubBytes,
173 * InvMixColumns, AddRoundKey).
174 */
175 "cmpb $13, %b4\n\t"
176 "jb 2f\n\t"
177 "je 1f\n\t"
178 /* 15 rounds (13 intermediate rounds) */
179 "aesdec 0x10(%0), %%xmm0\n\t"
180 "aesdec 0x20(%0), %%xmm0\n\t"
181 "lea 0x20(%0), %0\n\t"
182 "\n1:\n\t"
183 /* 13+ rounds (11+ intermediate rounds) */
184 "aesdec 0x10(%0), %%xmm0\n\t"
185 "aesdec 0x20(%0), %%xmm0\n\t"
186 "lea 0x20(%0), %0\n\t"
187 "\n2:\n\t"
188 /* 11+ rounds (9+ intermediate rounds) */
189 "aesdec 0x10(%0), %%xmm0\n\t"
190 "aesdec 0x20(%0), %%xmm0\n\t"
191 "aesdec 0x30(%0), %%xmm0\n\t"
192 "aesdec 0x40(%0), %%xmm0\n\t"
193 "aesdec 0x50(%0), %%xmm0\n\t"
194 "aesdec 0x60(%0), %%xmm0\n\t"
195 "aesdec 0x70(%0), %%xmm0\n\t"
196 "aesdec 0x80(%0), %%xmm0\n\t"
197 "aesdec 0x90(%0), %%xmm0\n\t"
198 /* Final round (InvShiftRows, InvSubBytes, AddRoundKey) */
199 "aesdeclast 0xa0(%0), %%xmm0\n\t"
200 "movdqu %%xmm0, %2\n\t"
201 /* Restore XMM register */
202 "movdqu %1, %%xmm0\n\t"
203 : "+r" ( key ), "=m" ( save ), "=m" ( *out )
204 : "m" ( *in ), "rm" ( aes->rounds ), "m" ( aes->decrypt ) );
205}
struct aes_round_keys decrypt
Decryption keys.
Definition aes.h:41

References __unused, aes_context(), assert, ctx, aes_context::decrypt, in, aes_round_keys::key, key, len, out, aes_context::rounds, and src.

Referenced by aes_accelerate().

◆ aes_accelerate()

void aes_accelerate ( void )

Enable hardware acceleration (if supported).

Definition at line 211 of file aesni.c.

211 {
212 struct x86_features features;
213
214 /* Detect AES-NI support */
216 if ( features.intel.ecx & CPUID_FEATURES_INTEL_ECX_AESNI ) {
217 DBGC ( &aes_algorithm, "AES enabled AES-NI acceleration\n" );
220 }
221}
struct cipher_algorithm aes_algorithm
Basic AES algorithm.
Definition aes.c:847
static void aesni_decrypt(struct cipher_algorithm *cipher __unused, void *ctx, const void *src, void *dst, size_t len)
Decrypt data.
Definition aesni.c:150
static void aesni_encrypt(struct cipher_algorithm *cipher __unused, void *ctx, const void *src, void *dst, size_t len)
Encrypt data.
Definition aesni.c:84
void x86_features(struct x86_features *features)
Get x86 CPU features.
Definition cpuid.c:164
#define CPUID_FEATURES_INTEL_ECX_AESNI
AES-NI instructions are supported.
Definition cpuid.h:47
uint32_t features
Supported features.
Definition ena.h:5
#define DBGC(...)
Definition compiler.h:530
x86 CPU features
Definition cpuid.h:24

References aes_algorithm, aesni_decrypt(), aesni_encrypt(), CPUID_FEATURES_INTEL_ECX_AESNI, DBGC, features, and x86_features().

Referenced by aes_hw_test_exec(), aes_setkey(), and aes_sw_test_exec().