iPXE
aes.c File Reference

AES algorithm. More...

#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/rotate.h>
#include <ipxe/crypto.h>
#include <ipxe/ecb.h>
#include <ipxe/cbc.h>
#include <ipxe/gcm.h>
#include <ipxe/aes.h>

Go to the source code of this file.

Data Structures

union  aes_table_entry
 A single AES lookup table entry. More...
struct  aes_table
 An AES lookup table. More...

Enumerations

enum  aes_stride { AES_STRIDE_SHIFTROWS = +5 , AES_STRIDE_INVSHIFTROWS = -3 }
 AES strides. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static uint32_t aes_entry_column (const union aes_table_entry *entry, unsigned int column)
 Multiply [Inv]MixColumns matrix column by scalar multiplicand.
static uint32_t aes_column (const struct aes_table *table, size_t stride, const union aes_matrix *in, size_t offset)
 Multiply [Inv]MixColumns matrix column by S-boxed input byte.
static uint32_t aes_output (const struct aes_table *table, size_t stride, const union aes_matrix *in, const union aes_matrix *key, unsigned int column)
 Calculate intermediate round output column.
static void aes_round (const struct aes_table *table, size_t stride, const union aes_matrix *in, union aes_matrix *out, const union aes_matrix *key)
 Perform a single intermediate round.
static const union aes_matrixaes_encrypt_rounds (union aes_matrix *in, union aes_matrix *out, const union aes_matrix *key, unsigned int rounds)
 Perform encryption intermediate rounds.
static const union aes_matrixaes_decrypt_rounds (union aes_matrix *in, union aes_matrix *out, const union aes_matrix *key, unsigned int rounds)
 Perform decryption intermediate rounds.
static void aes_addroundkey (union aes_matrix *state, const union aes_matrix *key)
 Perform standalone AddRoundKey.
static void aes_final (const struct aes_table *table, size_t stride, const union aes_matrix *in, union aes_matrix *out, const union aes_matrix *key)
 Perform final round.
static unsigned int aes_rounds (const struct aes_context *aes)
 Calculate number of intermediate rounds.
static void aes_encrypt (struct cipher_algorithm *cipher __unused, void *ctx, const void *src, void *dst, size_t len)
 Encrypt data.
static void aes_decrypt (struct cipher_algorithm *cipher __unused, void *ctx, const void *src, void *dst, size_t len)
 Decrypt data.
static unsigned int aes_double (unsigned int poly)
 Multiply a polynomial by (x) modulo (x^8 + x^4 + x^3 + x^2 + 1) in GF(2^8).
static void aes_mixcolumns_entry (union aes_table_entry *entry)
 Fill in MixColumns lookup table entry.
static void aes_invmixcolumns_entry (union aes_table_entry *entry)
 Fill in InvMixColumns lookup table entry.
static void aes_generate (void)
 Generate AES lookup tables.
static uint32_t aes_key_rotate (uint32_t column)
 Rotate key column.
static uint32_t aes_key_sbox (uint32_t column)
 Apply S-box to key column.
static uint32_t aes_key_rcon (uint32_t column, unsigned int rcon)
 Apply schedule round constant to key column.
static int aes_setkey (struct cipher_algorithm *cipher __unused, void *ctx, const void *key, size_t keylen)
 Set key.
void aes_decelerate (void)
 Disable hardware acceleration (for testing).
int aes_is_accelerated (void)
 Check if hardware acceleration is currently enabled (for testing).
 ECB_CIPHER (aes_ecb, aes_ecb_algorithm, aes_algorithm, struct aes_context, AES_BLOCKSIZE)
 CBC_CIPHER (aes_cbc, aes_cbc_algorithm, aes_algorithm, struct aes_context, AES_BLOCKSIZE)
 GCM_CIPHER (aes_gcm, aes_gcm_algorithm, aes_algorithm, struct aes_context, AES_BLOCKSIZE)

Variables

static struct aes_table aes_mixcolumns
 AES MixColumns lookup table.
static struct aes_table aes_invmixcolumns
 AES InvMixColumns lookup table.
static int aes_selected
 AES hardware acceleration mode has been selected.
struct cipher_algorithm aes_algorithm
 Basic AES algorithm.

Detailed Description

AES algorithm.

Definition in file aes.c.

Enumeration Type Documentation

◆ aes_stride

enum aes_stride

AES strides.

These are the strides (modulo 16) used to walk through the AES input state bytes in order of byte position after [Inv]ShiftRows.

Enumerator
AES_STRIDE_SHIFTROWS 

Input stride for ShiftRows.

0 4 8 c \ \ \ 1 5 9 d \ \ \ 2 6 a e \ \ \ 3 7 b f

AES_STRIDE_INVSHIFTROWS 

Input stride for InvShiftRows.

0 4 8 c / / / 1 5 9 d / / / 2 6 a e / / / 3 7 b f

Definition at line 50 of file aes.c.

50 {
51 /** Input stride for ShiftRows
52 *
53 * 0 4 8 c
54 * \ \ \
55 * 1 5 9 d
56 * \ \ \
57 * 2 6 a e
58 * \ \ \
59 * 3 7 b f
60 */
62 /** Input stride for InvShiftRows
63 *
64 * 0 4 8 c
65 * / / /
66 * 1 5 9 d
67 * / / /
68 * 2 6 a e
69 * / / /
70 * 3 7 b f
71 */
73};
@ AES_STRIDE_SHIFTROWS
Input stride for ShiftRows.
Definition aes.c:61
@ AES_STRIDE_INVSHIFTROWS
Input stride for InvShiftRows.
Definition aes.c:72

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ aes_entry_column()

uint32_t aes_entry_column ( const union aes_table_entry * entry,
unsigned int column )
inlinestatic

Multiply [Inv]MixColumns matrix column by scalar multiplicand.

Parameters
entryAES lookup table entry for scalar multiplicand
column[Inv]MixColumns matrix column index
Return values
productProduct of matrix column with scalar multiplicand

Definition at line 163 of file aes.c.

163 {
164 const union {
166 uint32_t column;
167 } __attribute__ (( may_alias )) *product;
168
169 /* Locate relevant four-byte subset */
170 product = container_of ( &entry->byte[ 4 - column ],
171 typeof ( *product ), byte );
172
173 /* Extract this four-byte subset */
174 return product->column;
175}
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
#define __attribute__(x)
Definition compiler.h:10
uint8_t product
Product string.
Definition smbios.h:5
unsigned char byte
Definition smc9000.h:38
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
uint8_t byte[8]
Viewed as an array of bytes.
Definition aes.c:115

References __attribute__, aes_table_entry::byte, container_of, product, and typeof().

Referenced by aes_column().

◆ aes_column()

uint32_t aes_column ( const struct aes_table * table,
size_t stride,
const union aes_matrix * in,
size_t offset )
inlinestatic

Multiply [Inv]MixColumns matrix column by S-boxed input byte.

Parameters
tableAES lookup table
strideAES row shift stride
inAES input state
offsetOutput byte offset (after [Inv]ShiftRows)
Return values
productProduct of matrix column with S(input byte)

Note that the specified offset is not the offset of the input byte; it is the offset of the output byte which corresponds to the input byte. This output byte offset is used to calculate both the input byte offset and to select the appropriate matric column.

With a compile-time constant offset, this function will optimise down to a single "movzbl" (to extract the input byte) and will generate a single x86 memory reference expression which can then be used directly within a single "xorl" instruction.

Definition at line 197 of file aes.c.

198 {
199 const union aes_table_entry *entry;
200 unsigned int byte;
201
202 /* Extract input byte corresponding to this output byte offset
203 * (i.e. perform [Inv]ShiftRows).
204 */
205 byte = in->byte[ ( stride * offset ) & 0xf ];
206
207 /* Locate lookup table entry for this input byte (i.e. perform
208 * [Inv]SubBytes).
209 */
210 entry = &table->entry[byte];
211
212 /* Multiply appropriate matrix column by this input byte
213 * (i.e. perform [Inv]MixColumns).
214 */
215 return aes_entry_column ( entry, ( offset & 0x3 ) );
216}
__be32 in[4]
Definition CIB_PRM.h:7
static uint32_t aes_entry_column(const union aes_table_entry *entry, unsigned int column)
Multiply [Inv]MixColumns matrix column by scalar multiplicand.
Definition aes.c:163
uint16_t offset
Offset to command line.
Definition bzimage.h:3
struct ena_llq_option stride
Descriptor strides.
Definition ena.h:11
union aes_table_entry entry[256]
Table entries, indexed by S(N).
Definition aes.c:143
A single AES lookup table entry.
Definition aes.c:113

References aes_entry_column(), aes_table::entry, in, offset, and stride.

Referenced by aes_output().

◆ aes_output()

uint32_t aes_output ( const struct aes_table * table,
size_t stride,
const union aes_matrix * in,
const union aes_matrix * key,
unsigned int column )
inlinestatic

Calculate intermediate round output column.

Parameters
tableAES lookup table
strideAES row shift stride
inAES input state
keyAES round key
columnColumn index
Return values
outputOutput column value

Definition at line 229 of file aes.c.

231 {
232 size_t offset = ( column * 4 );
233
234 /* Perform [Inv]ShiftRows, [Inv]SubBytes, [Inv]MixColumns, and
235 * AddRoundKey for this column. The loop is unrolled to allow
236 * for the required compile-time constant optimisations.
237 */
238 return ( aes_column ( table, stride, in, ( offset + 0 ) ) ^
239 aes_column ( table, stride, in, ( offset + 1 ) ) ^
240 aes_column ( table, stride, in, ( offset + 2 ) ) ^
241 aes_column ( table, stride, in, ( offset + 3 ) ) ^
242 key->column[column] );
243}
union @162305117151260234136356364136041353210355154177 key
static uint32_t aes_column(const struct aes_table *table, size_t stride, const union aes_matrix *in, size_t offset)
Multiply [Inv]MixColumns matrix column by S-boxed input byte.
Definition aes.c:197

References aes_column(), in, key, offset, and stride.

Referenced by aes_round().

◆ aes_round()

void aes_round ( const struct aes_table * table,
size_t stride,
const union aes_matrix * in,
union aes_matrix * out,
const union aes_matrix * key )
inlinestatic

Perform a single intermediate round.

Parameters
tableAES lookup table
strideAES row shift stride
inAES input state
outAES output state
keyAES round key

Definition at line 255 of file aes.c.

257 {
258
259 /* Perform [Inv]ShiftRows, [Inv]SubBytes, [Inv]MixColumns, and
260 * AddRoundKey for all columns. The loop is unrolled to allow
261 * for the required compile-time constant optimisations.
262 */
263 out->column[0] = aes_output ( table, stride, in, key, 0 );
264 out->column[1] = aes_output ( table, stride, in, key, 1 );
265 out->column[2] = aes_output ( table, stride, in, key, 2 );
266 out->column[3] = aes_output ( table, stride, in, key, 3 );
267}
__be32 out[4]
Definition CIB_PRM.h:8
static uint32_t aes_output(const struct aes_table *table, size_t stride, const union aes_matrix *in, const union aes_matrix *key, unsigned int column)
Calculate intermediate round output column.
Definition aes.c:229

References aes_output(), in, key, out, and stride.

Referenced by aes_decrypt_rounds(), and aes_encrypt_rounds().

◆ aes_encrypt_rounds()

const union aes_matrix * aes_encrypt_rounds ( union aes_matrix * in,
union aes_matrix * out,
const union aes_matrix * key,
unsigned int rounds )
static

Perform encryption intermediate rounds.

Parameters
inAES input state
outAES output state
keyRound keys
roundsNumber of intermediate rounds (must be odd)
Return values
keyFinal round key

This function is deliberately marked as non-inlinable to ensure maximal availability of registers for GCC's register allocator, which has a tendency to otherwise spill performance-critical registers to the stack.

Definition at line 284 of file aes.c.

285 {
286 union aes_matrix *tmp;
287
288 /* Perform intermediate rounds */
289 do {
290 /* Perform one intermediate round */
292 in, out, key++ );
293
294 /* Swap input and output states for next round */
295 tmp = in;
296 in = out;
297 out = tmp;
298
299 } while ( --rounds );
300
301 return key;
302}
static struct aes_table aes_mixcolumns
AES MixColumns lookup table.
Definition aes.c:147
static void aes_round(const struct aes_table *table, size_t stride, const union aes_matrix *in, union aes_matrix *out, const union aes_matrix *key)
Perform a single intermediate round.
Definition aes.c:255
unsigned long tmp
Definition linux_pci.h:65
AES matrix.
Definition aes.h:23

References aes_mixcolumns, aes_round(), AES_STRIDE_SHIFTROWS, in, key, out, and tmp.

Referenced by aes_encrypt().

◆ aes_decrypt_rounds()

const union aes_matrix * aes_decrypt_rounds ( union aes_matrix * in,
union aes_matrix * out,
const union aes_matrix * key,
unsigned int rounds )
static

Perform decryption intermediate rounds.

Parameters
inAES input state
outAES output state
keyRound keys
roundsNumber of intermediate rounds (must be odd)
Return values
keyFinal round key

As with aes_encrypt_rounds(), this function is deliberately marked as non-inlinable.

This function could potentially use the same binary code as is used for encryption. To compensate for the difference between ShiftRows and InvShiftRows, half of the input byte offsets would have to be modifiable at runtime (half by an offset of +4/-4, half by an offset of -4/+4 for ShiftRows/InvShiftRows). This can be accomplished in x86 assembly within the number of available registers, but GCC's register allocator struggles to do so, resulting in a significant performance decrease due to registers being spilled to the stack. We therefore use two separate but very similar binary functions based on the same C source.

Definition at line 328 of file aes.c.

329 {
330 union aes_matrix *tmp;
331
332 /* Perform intermediate rounds */
333 do {
334 /* Perform one intermediate round */
336 in, out, key++ );
337
338 /* Swap input and output states for next round */
339 tmp = in;
340 in = out;
341 out = tmp;
342
343 } while ( --rounds );
344
345 return key;
346}
static struct aes_table aes_invmixcolumns
AES InvMixColumns lookup table.
Definition aes.c:150

References aes_invmixcolumns, aes_round(), AES_STRIDE_INVSHIFTROWS, in, key, out, and tmp.

Referenced by aes_decrypt(), and aes_setkey().

◆ aes_addroundkey()

void aes_addroundkey ( union aes_matrix * state,
const union aes_matrix * key )
inlinestatic

Perform standalone AddRoundKey.

Parameters
stateAES state
keyAES round key

Definition at line 355 of file aes.c.

355 {
356
357 state->column[0] ^= key->column[0];
358 state->column[1] ^= key->column[1];
359 state->column[2] ^= key->column[2];
360 state->column[3] ^= key->column[3];
361}
uint8_t state
State.
Definition eth_slow.h:36

References key, and state.

Referenced by aes_decrypt(), aes_encrypt(), and aes_final().

◆ aes_final()

void aes_final ( const struct aes_table * table,
size_t stride,
const union aes_matrix * in,
union aes_matrix * out,
const union aes_matrix * key )
static

Perform final round.

Parameters
tableAES lookup table
strideAES row shift stride
inAES input state
outAES output state
keyAES round key

Definition at line 372 of file aes.c.

374 {
375 const union aes_table_entry *entry;
376 unsigned int byte;
377 size_t out_offset;
378 size_t in_offset;
379
380 /* Perform [Inv]ShiftRows and [Inv]SubBytes */
381 for ( out_offset = 0, in_offset = 0 ; out_offset < 16 ;
382 out_offset++, in_offset = ( ( in_offset + stride ) & 0xf ) ) {
383
384 /* Extract input byte (i.e. perform [Inv]ShiftRows) */
385 byte = in->byte[in_offset];
386
387 /* Locate lookup table entry for this input byte
388 * (i.e. perform [Inv]SubBytes).
389 */
390 entry = &table->entry[byte];
391
392 /* Store output byte */
393 out->byte[out_offset] = entry->byte[0];
394 }
395
396 /* Perform AddRoundKey */
398}
static void aes_addroundkey(union aes_matrix *state, const union aes_matrix *key)
Perform standalone AddRoundKey.
Definition aes.c:355

References aes_addroundkey(), aes_table_entry::byte, aes_table::entry, in, key, out, and stride.

Referenced by aes_decrypt(), aes_encrypt(), and aes_setkey().

◆ aes_rounds()

unsigned int aes_rounds ( const struct aes_context * aes)
static

Calculate number of intermediate rounds.

Parameters
aesAES context
Return values
roundsNumber of intermediate rounds (must be odd)

Definition at line 406 of file aes.c.

406 {
407 unsigned int rounds;
408
409 /* Ensure that the number of intermediate rounds is a safe
410 * value even on a completely uninitialized context.
411 */
412 rounds = ( ( aes->rounds & 6 ) + 7 );
413 assert ( rounds <= ( AES_MAX_ROUNDS - 2 ) );
414 assert ( rounds & 1 );
415 return rounds;
416}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
#define AES_MAX_ROUNDS
Maximum number of AES rounds.
Definition aes.h:20
uint8_t rounds
Number of rounds.
Definition aes.h:43

References AES_MAX_ROUNDS, assert, and aes_context::rounds.

Referenced by aes_decrypt(), and aes_encrypt().

◆ aes_encrypt()

void aes_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 427 of file aes.c.

428 {
429 const struct aes_context *aes = aes_context ( ctx );
430 const union aes_matrix *key = aes->encrypt.key;
431 union aes_matrix buffer[2];
432 union aes_matrix *in = &buffer[0];
433 union aes_matrix *out = &buffer[1];
434
435 /* Sanity check */
436 assert ( len == sizeof ( *in ) );
437
438 /* Initialise input state */
439 memcpy ( in, src, sizeof ( *in ) );
440
441 /* Perform initial round (AddRoundKey) */
442 aes_addroundkey ( in, key++ );
443
444 /* Perform intermediate rounds (ShiftRows, SubBytes,
445 * MixColumns, AddRoundKey).
446 */
447 key = aes_encrypt_rounds ( in, out, key, aes_rounds ( aes ) );
448 in = out;
449
450 /* Perform final round (ShiftRows, SubBytes, AddRoundKey) */
451 out = dst;
453}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
static void aes_final(const struct aes_table *table, size_t stride, const union aes_matrix *in, union aes_matrix *out, const union aes_matrix *key)
Perform final round.
Definition aes.c:372
static unsigned int aes_rounds(const struct aes_context *aes)
Calculate number of intermediate rounds.
Definition aes.c:406
static const union aes_matrix * aes_encrypt_rounds(union aes_matrix *in, union aes_matrix *out, const union aes_matrix *key, unsigned int rounds)
Perform encryption intermediate rounds.
Definition aes.c:284
static const void * src
Definition string.h:48
ring len
Length.
Definition dwmac.h:226
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER).
Definition netvsc.h:5
static struct aes_context * aes_context(void *ctx)
Align AES context.
Definition aes.h:55
void * memcpy(void *dest, const void *src, size_t len) __nonnull
AES context.
Definition aes.h:37
struct aes_round_keys encrypt
Encryption keys.
Definition aes.h:39
union aes_matrix key[AES_MAX_ROUNDS]
Round keys.
Definition aes.h:33

References __unused, aes_addroundkey(), aes_context(), aes_encrypt_rounds(), aes_final(), aes_mixcolumns, aes_rounds(), AES_STRIDE_SHIFTROWS, assert, buffer, ctx, aes_context::encrypt, in, aes_round_keys::key, key, len, memcpy(), out, and src.

Referenced by aes_decelerate(), and aes_is_accelerated().

◆ aes_decrypt()

void aes_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 decrypt
dstBuffer for decrypted data
lenLength of data

Definition at line 464 of file aes.c.

465 {
466 const struct aes_context *aes = aes_context ( ctx );
467 const union aes_matrix *key = aes->decrypt.key;
468 union aes_matrix buffer[2];
469 union aes_matrix *in = &buffer[0];
470 union aes_matrix *out = &buffer[1];
471
472 /* Sanity check */
473 assert ( len == sizeof ( *in ) );
474
475 /* Initialise input state */
476 memcpy ( in, src, sizeof ( *in ) );
477
478 /* Perform initial round (AddRoundKey) */
479 aes_addroundkey ( in, key++ );
480
481 /* Perform intermediate rounds (InvShiftRows, InvSubBytes,
482 * InvMixColumns, AddRoundKey).
483 */
484 key = aes_decrypt_rounds ( in, out, key, aes_rounds ( aes ) );
485 in = out;
486
487 /* Perform final round (InvShiftRows, InvSubBytes, AddRoundKey) */
488 out = dst;
490}
static const union aes_matrix * aes_decrypt_rounds(union aes_matrix *in, union aes_matrix *out, const union aes_matrix *key, unsigned int rounds)
Perform decryption intermediate rounds.
Definition aes.c:328
struct aes_round_keys decrypt
Decryption keys.
Definition aes.h:41

References __unused, aes_addroundkey(), aes_context(), aes_decrypt_rounds(), aes_final(), aes_invmixcolumns, aes_rounds(), AES_STRIDE_INVSHIFTROWS, assert, buffer, ctx, aes_context::decrypt, in, aes_round_keys::key, key, len, memcpy(), out, and src.

Referenced by aes_decelerate().

◆ aes_double()

unsigned int aes_double ( unsigned int poly)
static

Multiply a polynomial by (x) modulo (x^8 + x^4 + x^3 + x^2 + 1) in GF(2^8).

Parameters
polyPolynomial to be multiplied
Return values
resultResult

Definition at line 498 of file aes.c.

498 {
499
500 /* Multiply polynomial by (x), placing the resulting x^8
501 * coefficient in the LSB (i.e. rotate byte left by one).
502 */
503 poly = rol8 ( poly, 1 );
504
505 /* If coefficient of x^8 (in LSB) is non-zero, then reduce by
506 * subtracting (x^8 + x^4 + x^3 + x^2 + 1) in GF(2^8).
507 */
508 if ( poly & 0x01 ) {
509 poly ^= 0x01; /* Subtract x^8 (currently in LSB) */
510 poly ^= 0x1b; /* Subtract (x^4 + x^3 + x^2 + 1) */
511 }
512
513 return poly;
514}

References aes_double().

Referenced by aes_double(), aes_generate(), aes_invmixcolumns_entry(), aes_mixcolumns_entry(), and aes_setkey().

◆ aes_mixcolumns_entry()

void aes_mixcolumns_entry ( union aes_table_entry * entry)
static

Fill in MixColumns lookup table entry.

Parameters
entryAES lookup table entry for scalar multiplicand

The MixColumns lookup table vector multiplier is {1,1,1,3,2,1,1,3}.

Definition at line 523 of file aes.c.

523 {
524 unsigned int scalar_x_1;
525 unsigned int scalar_x;
526 unsigned int scalar;
527
528 /* Retrieve scalar multiplicand */
529 scalar = entry->byte[0];
530 entry->byte[1] = scalar;
531 entry->byte[2] = scalar;
532 entry->byte[5] = scalar;
533 entry->byte[6] = scalar;
534
535 /* Calculate scalar multiplied by (x) */
536 scalar_x = aes_double ( scalar );
537 entry->byte[4] = scalar_x;
538
539 /* Calculate scalar multiplied by (x + 1) */
540 scalar_x_1 = ( scalar_x ^ scalar );
541 entry->byte[3] = scalar_x_1;
542 entry->byte[7] = scalar_x_1;
543}
static unsigned int aes_double(unsigned int poly)
Multiply a polynomial by (x) modulo (x^8 + x^4 + x^3 + x^2 + 1) in GF(2^8).
Definition aes.c:498

References aes_double(), and aes_table_entry::byte.

Referenced by aes_generate().

◆ aes_invmixcolumns_entry()

void aes_invmixcolumns_entry ( union aes_table_entry * entry)
static

Fill in InvMixColumns lookup table entry.

Parameters
entryAES lookup table entry for scalar multiplicand

The InvMixColumns lookup table vector multiplier is {1,9,13,11,14,9,13,11}.

Definition at line 552 of file aes.c.

552 {
553 unsigned int scalar_x3_x2_x;
554 unsigned int scalar_x3_x2_1;
555 unsigned int scalar_x3_x2;
556 unsigned int scalar_x3_x_1;
557 unsigned int scalar_x3_1;
558 unsigned int scalar_x3;
559 unsigned int scalar_x2;
560 unsigned int scalar_x;
561 unsigned int scalar;
562
563 /* Retrieve scalar multiplicand */
564 scalar = entry->byte[0];
565
566 /* Calculate scalar multiplied by (x) */
567 scalar_x = aes_double ( scalar );
568
569 /* Calculate scalar multiplied by (x^2) */
570 scalar_x2 = aes_double ( scalar_x );
571
572 /* Calculate scalar multiplied by (x^3) */
573 scalar_x3 = aes_double ( scalar_x2 );
574
575 /* Calculate scalar multiplied by (x^3 + 1) */
576 scalar_x3_1 = ( scalar_x3 ^ scalar );
577 entry->byte[1] = scalar_x3_1;
578 entry->byte[5] = scalar_x3_1;
579
580 /* Calculate scalar multiplied by (x^3 + x + 1) */
581 scalar_x3_x_1 = ( scalar_x3_1 ^ scalar_x );
582 entry->byte[3] = scalar_x3_x_1;
583 entry->byte[7] = scalar_x3_x_1;
584
585 /* Calculate scalar multiplied by (x^3 + x^2) */
586 scalar_x3_x2 = ( scalar_x3 ^ scalar_x2 );
587
588 /* Calculate scalar multiplied by (x^3 + x^2 + 1) */
589 scalar_x3_x2_1 = ( scalar_x3_x2 ^ scalar );
590 entry->byte[2] = scalar_x3_x2_1;
591 entry->byte[6] = scalar_x3_x2_1;
592
593 /* Calculate scalar multiplied by (x^3 + x^2 + x) */
594 scalar_x3_x2_x = ( scalar_x3_x2 ^ scalar_x );
595 entry->byte[4] = scalar_x3_x2_x;
596}

References aes_double(), and aes_table_entry::byte.

Referenced by aes_generate().

◆ aes_generate()

void aes_generate ( void )
static

Generate AES lookup tables.

Definition at line 602 of file aes.c.

602 {
603 union aes_table_entry *entry;
604 union aes_table_entry *inventry;
605 unsigned int poly = 0x01;
606 unsigned int invpoly = 0x01;
607 unsigned int transformed;
608 unsigned int i;
609
610 /* Iterate over non-zero values of GF(2^8) using generator (x + 1) */
611 do {
612
613 /* Multiply polynomial by (x + 1) */
614 poly ^= aes_double ( poly );
615
616 /* Divide inverse polynomial by (x + 1). This code
617 * fragment is taken directly from the Wikipedia page
618 * on the Rijndael S-box. An explanation of why it
619 * works would be greatly appreciated.
620 */
621 invpoly ^= ( invpoly << 1 );
622 invpoly ^= ( invpoly << 2 );
623 invpoly ^= ( invpoly << 4 );
624 if ( invpoly & 0x80 )
625 invpoly ^= 0x09;
626 invpoly &= 0xff;
627
628 /* Apply affine transformation */
629 transformed = ( 0x63 ^ invpoly ^ rol8 ( invpoly, 1 ) ^
630 rol8 ( invpoly, 2 ) ^ rol8 ( invpoly, 3 ) ^
631 rol8 ( invpoly, 4 ) );
632
633 /* Populate S-box (within MixColumns lookup table) */
634 aes_mixcolumns.entry[poly].byte[0] = transformed;
635
636 } while ( poly != 0x01 );
637
638 /* Populate zeroth S-box entry (which has no inverse) */
639 aes_mixcolumns.entry[0].byte[0] = 0x63;
640
641 /* Fill in MixColumns and InvMixColumns lookup tables */
642 for ( i = 0 ; i < 256 ; i++ ) {
643
644 /* Fill in MixColumns lookup table entry */
645 entry = &aes_mixcolumns.entry[i];
646 aes_mixcolumns_entry ( entry );
647
648 /* Populate inverse S-box (within InvMixColumns lookup table) */
649 inventry = &aes_invmixcolumns.entry[ entry->byte[0] ];
650 inventry->byte[0] = i;
651
652 /* Fill in InvMixColumns lookup table entry */
653 aes_invmixcolumns_entry ( inventry );
654 }
655}
static void aes_mixcolumns_entry(union aes_table_entry *entry)
Fill in MixColumns lookup table entry.
Definition aes.c:523
static void aes_invmixcolumns_entry(union aes_table_entry *entry)
Fill in InvMixColumns lookup table entry.
Definition aes.c:552

References aes_double(), aes_invmixcolumns, aes_invmixcolumns_entry(), aes_mixcolumns, aes_mixcolumns_entry(), and aes_table_entry::byte.

Referenced by aes_setkey().

◆ aes_key_rotate()

uint32_t aes_key_rotate ( uint32_t column)
inlinestatic

Rotate key column.

Parameters
columnKey column
Return values
columnUpdated key column

Definition at line 664 of file aes.c.

664 {
665
666 return ( ( __BYTE_ORDER == __LITTLE_ENDIAN ) ?
667 ror32 ( column, 8 ) : rol32 ( column, 8 ) );
668}
#define __BYTE_ORDER
Definition endian.h:7
#define __LITTLE_ENDIAN
Constant representing little-endian byte order.
Definition endian.h:13
static u32 ror32(u32 v, int bits)
Rotate 32-bit value right.
Definition wpa_tkip.c:162
static u32 rol32(u32 v, int bits)
Rotate 32-bit value left.
Definition wpa_tkip.c:174

References __BYTE_ORDER, __LITTLE_ENDIAN, rol32(), and ror32().

Referenced by aes_setkey().

◆ aes_key_sbox()

uint32_t aes_key_sbox ( uint32_t column)
static

Apply S-box to key column.

Parameters
columnKey column
Return values
columnUpdated key column

Definition at line 676 of file aes.c.

676 {
677 unsigned int i;
679
680 for ( i = 0 ; i < 4 ; i++ ) {
681 byte = ( column & 0xff );
682 byte = aes_mixcolumns.entry[byte].byte[0];
683 column = ( ( column & ~0xff ) | byte );
684 column = rol32 ( column, 8 );
685 }
686 return column;
687}

References aes_mixcolumns, and rol32().

Referenced by aes_setkey().

◆ aes_key_rcon()

uint32_t aes_key_rcon ( uint32_t column,
unsigned int rcon )
inlinestatic

Apply schedule round constant to key column.

Parameters
columnKey column
rconRound constant
Return values
columnUpdated key column

Definition at line 697 of file aes.c.

697 {
698
699 return ( ( __BYTE_ORDER == __LITTLE_ENDIAN ) ?
700 ( column ^ rcon ) : ( column ^ ( rcon << 24 ) ) );
701}

References __BYTE_ORDER, and __LITTLE_ENDIAN.

Referenced by aes_setkey().

◆ aes_setkey()

int aes_setkey ( struct cipher_algorithm *cipher __unused,
void * ctx,
const void * key,
size_t keylen )
static

Set key.

Parameters
cipherCipher algorithm
ctxContext
keyKey
keylenKey length
Return values
rcReturn status code

Definition at line 712 of file aes.c.

713 {
714 struct aes_context *aes = aes_context ( ctx );
715 union aes_matrix *enc;
716 union aes_matrix *dec;
717 union aes_matrix temp;
718 union aes_matrix zero;
719 unsigned int rcon = 0x01;
720 unsigned int rounds;
721 size_t offset = 0;
722 uint32_t *prev;
723 uint32_t *next;
724 uint32_t *end;
726
727 /* Attempt (once) to enable AES hardware acceleration */
728 if ( ! aes_selected ) {
730 aes_selected = 1;
731 }
732
733 /* Generate lookup tables, if not already done */
734 if ( ! aes_mixcolumns.entry[0].byte[0] )
735 aes_generate();
736
737 /* Validate key length and calculate number of intermediate rounds */
738 switch ( keylen ) {
739 case ( 128 / 8 ) :
740 rounds = 11;
741 break;
742 case ( 192 / 8 ) :
743 rounds = 13;
744 break;
745 case ( 256 / 8 ) :
746 rounds = 15;
747 break;
748 default:
749 DBGC ( aes, "AES %p unsupported key length (%zd bits)\n",
750 aes, ( keylen * 8 ) );
751 return -EINVAL;
752 }
753 aes->rounds = rounds;
754 enc = aes->encrypt.key;
755 end = enc[rounds].column;
756
757 /* Copy raw key */
758 memcpy ( enc, key, keylen );
759 prev = enc->column;
760 next = ( ( ( void * ) prev ) + keylen );
761 tmp = next[-1];
762
763 /* Construct expanded key */
764 while ( next < end ) {
765
766 /* If this is the first column of an expanded key
767 * block, or the middle column of an AES-256 key
768 * block, then apply the S-box.
769 */
770 if ( ( offset == 0 ) || ( ( offset | keylen ) == 48 ) )
771 tmp = aes_key_sbox ( tmp );
772
773 /* If this is the first column of an expanded key
774 * block then rotate and apply the round constant.
775 */
776 if ( offset == 0 ) {
777 tmp = aes_key_rotate ( tmp );
778 tmp = aes_key_rcon ( tmp, rcon );
779 rcon = aes_double ( rcon );
780 }
781
782 /* XOR with previous key column */
783 tmp ^= *prev;
784
785 /* Store column */
786 *next = tmp;
787
788 /* Move to next column */
789 offset += sizeof ( *next );
790 if ( offset == keylen )
791 offset = 0;
792 next++;
793 prev++;
794 }
795 DBGC2 ( aes, "AES %p expanded %zd-bit key:\n", aes, ( keylen * 8 ) );
796 DBGC2_HDA ( aes, 0, &aes->encrypt, ( rounds * sizeof ( *enc ) ) );
797
798 /* Convert to decryption key */
799 memset ( &zero, 0, sizeof ( zero ) );
800 dec = &aes->decrypt.key[ rounds - 1 ];
801 memcpy ( dec--, enc++, sizeof ( *dec ) );
802 while ( dec > aes->decrypt.key ) {
803 /* Perform InvMixColumns (by reusing the encryption
804 * final-round code to perform ShiftRows+SubBytes and
805 * reusing the decryption intermediate-round code to
806 * perform InvShiftRows+InvSubBytes+InvMixColumns, all
807 * with a zero encryption key).
808 */
810 enc++, &temp, &zero );
811 aes_decrypt_rounds ( &temp, dec--, &zero, 1 );
812 }
813 memcpy ( dec--, enc++, sizeof ( *dec ) );
814 DBGC2 ( aes, "AES %p inverted %zd-bit key:\n", aes, ( keylen * 8 ) );
815 DBGC2_HDA ( aes, 0, &aes->decrypt, ( rounds * sizeof ( *dec ) ) );
816
817 return 0;
818}
static uint32_t aes_key_sbox(uint32_t column)
Apply S-box to key column.
Definition aes.c:676
static void aes_generate(void)
Generate AES lookup tables.
Definition aes.c:602
static uint32_t aes_key_rcon(uint32_t column, unsigned int rcon)
Apply schedule round constant to key column.
Definition aes.c:697
static int aes_selected
AES hardware acceleration mode has been selected.
Definition aes.c:153
static uint32_t aes_key_rotate(uint32_t column)
Rotate key column.
Definition aes.c:664
void aes_accelerate(void)
Enable hardware acceleration (if supported).
Definition aesni.c:211
uint32_t next
Next descriptor address.
Definition dwmac.h:11
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
#define EINVAL
Invalid argument.
Definition errno.h:472
void * memset(void *dest, int character, size_t len) __nonnull
uint32_t end
Ending offset.
Definition netvsc.h:7
uint32_t column[4]
Viewed as an array of four-byte columns.
Definition aes.h:27

References __unused, aes_accelerate(), aes_context(), aes_decrypt_rounds(), aes_double(), aes_final(), aes_generate(), aes_key_rcon(), aes_key_rotate(), aes_key_sbox(), aes_mixcolumns, aes_selected, AES_STRIDE_SHIFTROWS, aes_matrix::column, ctx, DBGC, DBGC2, DBGC2_HDA, aes_context::decrypt, EINVAL, aes_context::encrypt, end, aes_round_keys::key, key, memcpy(), memset(), next, offset, aes_context::rounds, and tmp.

◆ aes_decelerate()

void aes_decelerate ( void )

Disable hardware acceleration (for testing).

Definition at line 824 of file aes.c.

824 {
825
826 /* Restore original algorithm pointers */
827 aes_algorithm.encrypt = aes_encrypt;
828 aes_algorithm.decrypt = aes_decrypt;
829 DBGC ( &aes_algorithm, "AES disabled hardware acceleration\n" );
830
831 /* Mark hardware acceleration mode as selected */
832 aes_selected = 1;
833}
struct cipher_algorithm aes_algorithm
Basic AES algorithm.
Definition aes.c:847
static void aes_encrypt(struct cipher_algorithm *cipher __unused, void *ctx, const void *src, void *dst, size_t len)
Encrypt data.
Definition aes.c:427
static void aes_decrypt(struct cipher_algorithm *cipher __unused, void *ctx, const void *src, void *dst, size_t len)
Decrypt data.
Definition aes.c:464

References aes_algorithm, aes_decrypt(), aes_encrypt(), aes_selected, and DBGC.

Referenced by aes_sw_test_exec().

◆ aes_is_accelerated()

int aes_is_accelerated ( void )

Check if hardware acceleration is currently enabled (for testing).

Return values
is_acceleratedAES is using hardware acceleration

Definition at line 840 of file aes.c.

840 {
841
842 /* Check if hardware acceleration is enabled */
843 return ( aes_algorithm.encrypt != aes_encrypt );
844}

References aes_algorithm, and aes_encrypt().

Referenced by aes_hw_test_exec().

◆ ECB_CIPHER()

ECB_CIPHER ( aes_ecb ,
aes_ecb_algorithm ,
aes_algorithm ,
struct aes_context ,
AES_BLOCKSIZE  )

◆ CBC_CIPHER()

CBC_CIPHER ( aes_cbc ,
aes_cbc_algorithm ,
aes_algorithm ,
struct aes_context ,
AES_BLOCKSIZE  )

◆ GCM_CIPHER()

GCM_CIPHER ( aes_gcm ,
aes_gcm_algorithm ,
aes_algorithm ,
struct aes_context ,
AES_BLOCKSIZE  )

Variable Documentation

◆ aes_mixcolumns

struct aes_table aes_mixcolumns
static

AES MixColumns lookup table.

Definition at line 147 of file aes.c.

Referenced by aes_encrypt(), aes_encrypt_rounds(), aes_generate(), aes_key_sbox(), and aes_setkey().

◆ aes_invmixcolumns

struct aes_table aes_invmixcolumns
static

AES InvMixColumns lookup table.

Definition at line 150 of file aes.c.

Referenced by aes_decrypt(), aes_decrypt_rounds(), and aes_generate().

◆ aes_selected

int aes_selected
static

AES hardware acceleration mode has been selected.

Definition at line 153 of file aes.c.

Referenced by aes_decelerate(), and aes_setkey().

◆ aes_algorithm

struct cipher_algorithm aes_algorithm
Initial value:
= {
.name = "aes",
.ctxsize = sizeof ( struct aes_context ),
.blocksize = AES_BLOCKSIZE,
.alignsize = 0,
.authsize = 0,
.confidential = 1,
.setkey = aes_setkey,
.encrypt = aes_encrypt,
.decrypt = aes_decrypt,
}
static int aes_setkey(struct cipher_algorithm *cipher __unused, void *ctx, const void *key, size_t keylen)
Set key.
Definition aes.c:712
int cipher_null_setiv(struct cipher_algorithm *cipher __unused, void *ctx __unused, const void *iv __unused, size_t ivlen __unused)
Definition crypto_null.c:70
void cipher_null_auth(struct cipher_algorithm *cipher __unused, void *ctx __unused, void *auth __unused)
Definition crypto_null.c:89
#define AES_BLOCKSIZE
AES blocksize.
Definition aes.h:17

Basic AES algorithm.

Definition at line 847 of file aes.c.

847 {
848 .name = "aes",
849 .ctxsize = sizeof ( struct aes_context ),
850 .blocksize = AES_BLOCKSIZE,
851 .alignsize = 0,
852 .authsize = 0,
853 .confidential = 1,
854 .setkey = aes_setkey,
855 .setiv = cipher_null_setiv,
856 .encrypt = aes_encrypt,
857 .decrypt = aes_decrypt,
858 .auth = cipher_null_auth,
859};

Referenced by aes_accelerate(), aes_decelerate(), aes_is_accelerated(), aes_unwrap(), aes_wrap(), CBC_CIPHER(), ccmp_cbc_mac(), ccmp_ctr_xor(), ccmp_feed_cbc_mac(), ccmp_init(), ECB_CIPHER(), and GCM_CIPHER().