532 lines
16 KiB
Plaintext
532 lines
16 KiB
Plaintext
note
|
|
description: "Tagging class for various size/speed tradeoffs of AES"
|
|
author: "Colin LeMahieu"
|
|
date: "$Date$"
|
|
revision: "$Revision$"
|
|
quote: "Talk is cheap - except when Congress does it. - Cullen Hightower"
|
|
|
|
deferred class
|
|
AES_ENGINE
|
|
|
|
inherit
|
|
AES_COMMON
|
|
BYTE_FACILITIES
|
|
|
|
feature
|
|
make_tables
|
|
do
|
|
two_table := multiply_table (0x2)
|
|
three_table := multiply_table (0x3)
|
|
nine_table := multiply_table (0x9)
|
|
eleven_table := multiply_table (0xb)
|
|
thirteen_table := multiply_table (0xd)
|
|
fourteen_table := multiply_table (0xe)
|
|
end
|
|
|
|
block_size: INTEGER = 16
|
|
|
|
feature
|
|
mcol (x: NATURAL_32): NATURAL_32
|
|
local
|
|
f2: NATURAL_32
|
|
do
|
|
f2 := FFmulX (x)
|
|
result := f2.bit_xor (rotate_right_32 (x.bit_xor (f2), 8)).bit_xor (rotate_right_32 (x, 16)).bit_xor (rotate_right_32 (x, 24))
|
|
end
|
|
|
|
-- State matrix columns
|
|
column_0: NATURAL_32
|
|
column_1: NATURAL_32
|
|
column_2: NATURAL_32
|
|
column_3: NATURAL_32
|
|
|
|
feature --Prepare input blocks for processing and return
|
|
unpack (bytes: SPECIAL [NATURAL_8] offset: INTEGER)
|
|
require
|
|
bytes.valid_index (offset)
|
|
bytes.valid_index (offset + 15)
|
|
local
|
|
index: INTEGER
|
|
do
|
|
index := bytes.lower
|
|
column_0 := as_natural_32_be (bytes, offset + index)
|
|
column_1 := as_natural_32_be (bytes, offset + index + 4)
|
|
column_2 := as_natural_32_be (bytes, offset + index + 8)
|
|
column_3 := as_natural_32_be (bytes, offset + index + 12)
|
|
ensure
|
|
bytes_match_blocks (bytes)
|
|
end
|
|
|
|
pack (bytes: SPECIAL [NATURAL_8] offset: INTEGER)
|
|
require
|
|
bytes.valid_index (offset)
|
|
bytes.valid_index (offset + 15)
|
|
local
|
|
index: INTEGER
|
|
do
|
|
index := bytes.lower
|
|
from_natural_32_be (column_0, bytes, offset + index)
|
|
from_natural_32_be (column_1, bytes, offset + index + 4)
|
|
from_natural_32_be (column_2, bytes, offset + index + 8)
|
|
from_natural_32_be (column_3, bytes, offset + index + 12)
|
|
ensure
|
|
bytes_match_blocks (bytes)
|
|
end
|
|
|
|
bytes_match_blocks (bytes: SPECIAL [NATURAL_8]): BOOLEAN
|
|
do
|
|
result := true
|
|
result := result and bytes [0] = (column_0 |>> 24 & 0xff).to_natural_8
|
|
result := result and bytes [1] = (column_0 |>> 16 & 0xff).to_natural_8
|
|
result := result and bytes [2] = (column_0 |>> 8 & 0xff).to_natural_8
|
|
result := result and bytes [3] = (column_0 & 0xff).to_natural_8
|
|
result := result and bytes [4] = (column_1 |>> 24 & 0xff).to_natural_8
|
|
result := result and bytes [5] = (column_1 |>> 16 & 0xff).to_natural_8
|
|
result := result and bytes [6] = (column_1 |>> 8 & 0xff).to_natural_8
|
|
result := result and bytes [7] = (column_1 & 0xff).to_natural_8
|
|
result := result and bytes [8] = (column_2 |>> 24 & 0xff).to_natural_8
|
|
result := result and bytes [9] = (column_2 |>> 16 & 0xff).to_natural_8
|
|
result := result and bytes [10] = (column_2 |>> 8 & 0xff).to_natural_8
|
|
result := result and bytes [11] = (column_2 & 0xff).to_natural_8
|
|
result := result and bytes [12] = (column_3 |>> 24 & 0xff).to_natural_8
|
|
result := result and bytes [13] = (column_3 |>> 16 & 0xff).to_natural_8
|
|
result := result and bytes [14] = (column_3 |>> 8 & 0xff).to_natural_8
|
|
result := result and bytes [15] = (column_3 & 0xff).to_natural_8
|
|
ensure
|
|
bytes [0] = (column_0 & 0xff).to_natural_8
|
|
bytes [1] = (column_0 |>> 8 & 0xff).to_natural_8
|
|
bytes [2] = (column_0 |>> 16 & 0xff).to_natural_8
|
|
bytes [3] = (column_0 |>> 24 & 0xff).to_natural_8
|
|
bytes [4] = (column_1 & 0xff).to_natural_8
|
|
bytes [5] = (column_1 |>> 8 & 0xff).to_natural_8
|
|
bytes [6] = (column_1 |>> 16 & 0xff).to_natural_8
|
|
bytes [7] = (column_1 |>> 24 & 0xff).to_natural_8
|
|
bytes [8] = (column_2 & 0xff).to_natural_8
|
|
bytes [9] = (column_2 |>> 8 & 0xff).to_natural_8
|
|
bytes [10] = (column_2 |>> 16 & 0xff).to_natural_8
|
|
bytes [11] = (column_2 |>> 24 & 0xff).to_natural_8
|
|
bytes [12] = (column_3 & 0xff).to_natural_8
|
|
bytes [13] = (column_3 |>> 8 & 0xff).to_natural_8
|
|
bytes [14] = (column_3 |>> 16 & 0xff).to_natural_8
|
|
bytes [15] = (column_3 |>> 24 & 0xff).to_natural_8
|
|
end
|
|
|
|
feature
|
|
encrypt_work (max_index: INTEGER)
|
|
local
|
|
index: INTEGER
|
|
do
|
|
add_round_key (index)
|
|
from
|
|
index := 4
|
|
until
|
|
index >= max_index - 4
|
|
loop
|
|
sub_columns
|
|
shift_rows
|
|
mix_columns
|
|
add_round_key (index)
|
|
index := index + 4
|
|
variant
|
|
max_index - index + 2
|
|
end
|
|
sub_columns
|
|
shift_rows
|
|
add_round_key (index)
|
|
end
|
|
|
|
decrypt_work (max_index: INTEGER)
|
|
local
|
|
index: INTEGER
|
|
do
|
|
index := max_index - 3
|
|
add_round_key (index)
|
|
from
|
|
index := index - 4
|
|
until
|
|
index = 0
|
|
loop
|
|
inv_shift_rows
|
|
inv_sub_columns
|
|
add_round_key (index)
|
|
inv_mix_columns
|
|
index := index - 4
|
|
variant
|
|
index + 1
|
|
end
|
|
inv_shift_rows
|
|
inv_sub_columns
|
|
add_round_key (index)
|
|
end
|
|
|
|
inv_sub_columns
|
|
do
|
|
column_0 := inv_sub_bytes (column_0)
|
|
column_1 := inv_sub_bytes (column_1)
|
|
column_2 := inv_sub_bytes (column_2)
|
|
column_3 := inv_sub_bytes (column_3)
|
|
end
|
|
|
|
inv_mix_columns
|
|
do
|
|
column_0 := inv_mix_column (column_0)
|
|
column_1 := inv_mix_column (column_1)
|
|
column_2 := inv_mix_column (column_2)
|
|
column_3 := inv_mix_column (column_3)
|
|
end
|
|
|
|
mix_columns
|
|
do
|
|
column_0 := mix_column (column_0)
|
|
column_1 := mix_column (column_1)
|
|
column_2 := mix_column (column_2)
|
|
column_3 := mix_column (column_3)
|
|
end
|
|
|
|
inv_mix_column (in: NATURAL_32): NATURAL_32
|
|
do
|
|
result := inv_mix_0 (in)
|
|
result := result | inv_mix_1 (in)
|
|
result := result | inv_mix_2 (in)
|
|
result := result | inv_mix_3 (in)
|
|
end
|
|
|
|
inv_mix_0 (in: NATURAL_32): NATURAL_32
|
|
local
|
|
part_0: NATURAL_32
|
|
part_1: NATURAL_32
|
|
part_2: NATURAL_32
|
|
part_3: NATURAL_32
|
|
do
|
|
part_0 := multiply_and_reduce ((in |>> 24 & 0xff).to_natural_8, 0xe)
|
|
part_1 := multiply_and_reduce ((in |>> 16 & 0xff).to_natural_8, 0xb)
|
|
part_2 := multiply_and_reduce ((in |>> 8 & 0xff).to_natural_8, 0xd)
|
|
part_3 := multiply_and_reduce ((in & 0xff).to_natural_8, 0x9)
|
|
result := part_0.bit_xor (part_1).bit_xor (part_2).bit_xor (part_3) |<< 24
|
|
end
|
|
|
|
inv_mix_1 (in: NATURAL_32): NATURAL_32
|
|
local
|
|
part_0: NATURAL_32
|
|
part_1: NATURAL_32
|
|
part_2: NATURAL_32
|
|
part_3: NATURAL_32
|
|
do
|
|
part_0 := multiply_and_reduce ((in |>> 24 & 0xff).to_natural_8, 0x9)
|
|
part_1 := multiply_and_reduce ((in |>> 16 & 0xff).to_natural_8, 0xe)
|
|
part_2 := multiply_and_reduce ((in |>> 8 & 0xff).to_natural_8, 0xb)
|
|
part_3 := multiply_and_reduce ((in & 0xff).to_natural_8, 0xd)
|
|
result := part_0.bit_xor (part_1).bit_xor (part_2).bit_xor (part_3) |<< 16
|
|
end
|
|
|
|
inv_mix_2 (in: NATURAL_32): NATURAL_32
|
|
local
|
|
part_0: NATURAL_32
|
|
part_1: NATURAL_32
|
|
part_2: NATURAL_32
|
|
part_3: NATURAL_32
|
|
do
|
|
part_0 := multiply_and_reduce ((in |>> 24 & 0xff).to_natural_8, 0xd)
|
|
part_1 := multiply_and_reduce ((in |>> 16 & 0xff).to_natural_8, 0x9)
|
|
part_2 := multiply_and_reduce ((in |>> 8 & 0xff).to_natural_8, 0xe)
|
|
part_3 := multiply_and_reduce ((in & 0xff).to_natural_8, 0xb)
|
|
result := part_0.bit_xor (part_1).bit_xor (part_2).bit_xor (part_3) |<< 8
|
|
end
|
|
|
|
inv_mix_3 (in: NATURAL_32): NATURAL_32
|
|
local
|
|
part_0: NATURAL_32
|
|
part_1: NATURAL_32
|
|
part_2: NATURAL_32
|
|
part_3: NATURAL_32
|
|
do
|
|
part_0 := multiply_and_reduce ((in |>> 24 & 0xff).to_natural_8, 0xb)
|
|
part_1 := multiply_and_reduce ((in |>> 16 & 0xff).to_natural_8, 0xd)
|
|
part_2 := multiply_and_reduce ((in |>> 8 & 0xff).to_natural_8, 0x9)
|
|
part_3 := multiply_and_reduce ((in & 0xff).to_natural_8, 0xe)
|
|
result := part_0.bit_xor (part_1).bit_xor (part_2).bit_xor (part_3)
|
|
end
|
|
|
|
mix_column (in: NATURAL_32): NATURAL_32
|
|
do
|
|
result := mix_0 (in)
|
|
result := result | mix_1 (in)
|
|
result := result | mix_2 (in)
|
|
result := result | mix_3 (in)
|
|
end
|
|
|
|
mix_0 (in: NATURAL_32): NATURAL_32
|
|
local
|
|
part_0: NATURAL_32
|
|
part_1: NATURAL_32
|
|
part_2: NATURAL_32
|
|
part_3: NATURAL_32
|
|
do
|
|
part_0 := multiply_and_reduce ((in |>> 24 & 0xff).to_natural_8, 0x2)
|
|
part_1 := multiply_and_reduce ((in |>> 16 & 0xff).to_natural_8, 0x3)
|
|
part_2 := in |>> 8 & 0xff
|
|
part_3 := in & 0xff
|
|
result := part_0.bit_xor (part_1).bit_xor (part_2).bit_xor (part_3) |<< 24
|
|
end
|
|
|
|
mix_1 (in: NATURAL_32): NATURAL_32
|
|
local
|
|
part_0: NATURAL_32
|
|
part_1: NATURAL_32
|
|
part_2: NATURAL_32
|
|
part_3: NATURAL_32
|
|
do
|
|
part_0 := (in |>> 24 & 0xff)
|
|
part_1 := multiply_and_reduce ((in |>> 16 & 0xff).to_natural_8, 0x2)
|
|
part_2 := multiply_and_reduce ((in |>> 8 & 0xff).to_natural_8, 0x3)
|
|
part_3 := in & 0xff
|
|
result := part_0.bit_xor (part_1).bit_xor (part_2).bit_xor (part_3) |<< 16
|
|
end
|
|
|
|
mix_2 (in: NATURAL_32): NATURAL_32
|
|
local
|
|
part_0: NATURAL_32
|
|
part_1: NATURAL_32
|
|
part_2: NATURAL_32
|
|
part_3: NATURAL_32
|
|
do
|
|
part_0 := in |>> 24 & 0xff
|
|
part_1 := in |>> 16 & 0xff
|
|
part_2 := multiply_and_reduce ((in |>> 8 & 0xff).to_natural_8, 0x2)
|
|
part_3 := multiply_and_reduce ((in & 0xff).to_natural_8, 0x3)
|
|
result := part_0.bit_xor (part_1).bit_xor (part_2).bit_xor (part_3) |<< 8
|
|
end
|
|
|
|
mix_3 (in: NATURAL_32): NATURAL_32
|
|
local
|
|
part_0: NATURAL_32
|
|
part_1: NATURAL_32
|
|
part_2: NATURAL_32
|
|
part_3: NATURAL_32
|
|
do
|
|
part_0 := multiply_and_reduce ((in |>> 24 & 0xff).to_natural_8, 0x3)
|
|
part_1 := in |>> 16 & 0xff
|
|
part_2 := in |>> 8 & 0xff
|
|
part_3 := multiply_and_reduce ((in & 0xff).to_natural_8, 0x2)
|
|
result := part_0.bit_xor (part_1).bit_xor (part_2).bit_xor (part_3)
|
|
end
|
|
|
|
sub_columns
|
|
do
|
|
column_0 := sub_bytes (column_0)
|
|
column_1 := sub_bytes (column_1)
|
|
column_2 := sub_bytes (column_2)
|
|
column_3 := sub_bytes (column_3)
|
|
end
|
|
|
|
inv_shift_rows
|
|
local
|
|
column_0_new: NATURAL_32
|
|
column_1_new: NATURAL_32
|
|
column_2_new: NATURAL_32
|
|
column_3_new: NATURAL_32
|
|
do
|
|
column_0_new := column_0 & 0xff000000
|
|
column_0_new := column_0_new | (column_3 & 0x00ff0000)
|
|
column_0_new := column_0_new | (column_2 & 0x0000ff00)
|
|
column_0_new := column_0_new | (column_1 & 0x000000ff)
|
|
column_1_new := column_1 & 0xff000000
|
|
column_1_new := column_1_new | (column_0 & 0x00ff0000)
|
|
column_1_new := column_1_new | (column_3 & 0x0000ff00)
|
|
column_1_new := column_1_new | (column_2 & 0x000000ff)
|
|
column_2_new := column_2 & 0xff000000
|
|
column_2_new := column_2_new | (column_1 & 0x00ff0000)
|
|
column_2_new := column_2_new | (column_0 & 0x0000ff00)
|
|
column_2_new := column_2_new | (column_3 & 0x000000ff)
|
|
column_3_new := column_3 & 0xff000000
|
|
column_3_new := column_3_new | (column_2 & 0x00ff0000)
|
|
column_3_new := column_3_new | (column_1 & 0x0000ff00)
|
|
column_3_new := column_3_new | (column_0 & 0x000000ff)
|
|
column_0 := column_0_new
|
|
column_1 := column_1_new
|
|
column_2 := column_2_new
|
|
column_3 := column_3_new
|
|
ensure
|
|
column_0 |>> 24 & 0xff = old column_0 |>> 24 & 0xff
|
|
column_0 |>> 16 & 0xff = old column_3 |>> 16 & 0xff
|
|
column_0 |>> 8 & 0xff = old column_2 |>> 8 & 0xff
|
|
column_0 & 0xff = old column_1 & 0xff
|
|
column_1 |>> 24 & 0xff = old column_1 |>> 24 & 0xff
|
|
column_1 |>> 16 & 0xff = old column_0 |>> 16 & 0xff
|
|
column_1 |>> 8 & 0xff = old column_3 |>> 8 & 0xff
|
|
column_1 & 0xff = old column_2 & 0xff
|
|
column_2 |>> 24 & 0xff = old column_2 |>> 24& 0xff
|
|
column_2 |>> 16 & 0xff = old column_1 |>> 16 & 0xff
|
|
column_2 |>> 8 & 0xff = old column_0 |>> 8 & 0xff
|
|
column_2 & 0xff = old column_3 & 0xff
|
|
column_3 |>> 24& 0xff = old column_3 |>> 24 & 0xff
|
|
column_3 |>> 16 & 0xff = old column_2 |>> 16 & 0xff
|
|
column_3 |>> 8 & 0xff = old column_1 |>> 8 & 0xff
|
|
column_3 & 0xff = old column_0 & 0xff
|
|
end
|
|
|
|
shift_rows
|
|
local
|
|
column_0_new: NATURAL_32
|
|
column_1_new: NATURAL_32
|
|
column_2_new: NATURAL_32
|
|
column_3_new: NATURAL_32
|
|
do
|
|
column_0_new := column_0 & 0xff000000
|
|
column_0_new := column_0_new | (column_1 & 0x00ff0000)
|
|
column_0_new := column_0_new | (column_2 & 0x0000ff00)
|
|
column_0_new := column_0_new | (column_3 & 0x000000ff)
|
|
column_1_new := column_1 & 0xff000000
|
|
column_1_new := column_1_new | (column_2 & 0x00ff0000)
|
|
column_1_new := column_1_new | (column_3 & 0x0000ff00)
|
|
column_1_new := column_1_new | (column_0 & 0x000000ff)
|
|
column_2_new := column_2 & 0xff000000
|
|
column_2_new := column_2_new | (column_3 & 0x00ff0000)
|
|
column_2_new := column_2_new | (column_0 & 0x0000ff00)
|
|
column_2_new := column_2_new | (column_1 & 0x000000ff)
|
|
column_3_new := column_3 & 0xff000000
|
|
column_3_new := column_3_new | (column_0 & 0x00ff0000)
|
|
column_3_new := column_3_new | (column_1 & 0x0000ff00)
|
|
column_3_new := column_3_new | (column_2 & 0x000000ff)
|
|
column_0 := column_0_new
|
|
column_1 := column_1_new
|
|
column_2 := column_2_new
|
|
column_3 := column_3_new
|
|
ensure
|
|
column_0 |>> 24 & 0xff = old column_0 |>> 24 & 0xff
|
|
column_0 |>> 16 & 0xff = old column_1 |>> 16 & 0xff
|
|
column_0 |>> 8 & 0xff = old column_2 |>> 8 & 0xff
|
|
column_0 & 0xff = old column_3 & 0xff
|
|
column_1 |>> 24 & 0xff = old column_1 |>> 24 & 0xff
|
|
column_1 |>> 16 & 0xff = old column_2 |>> 16 & 0xff
|
|
column_1 |>> 8 & 0xff = old column_3 |>> 8 & 0xff
|
|
column_1 & 0xff = old column_0 & 0xff
|
|
column_2 |>> 24 & 0xff = old column_2 |>> 24 & 0xff
|
|
column_2 |>> 16 & 0xff = old column_3 |>> 16 & 0xff
|
|
column_2 |>> 8 & 0xff = old column_0 |>> 8 & 0xff
|
|
column_2 & 0xff = old column_1 & 0xff
|
|
column_3 |>> 24 & 0xff = old column_3 |>> 24 & 0xff
|
|
column_3 |>> 16 & 0xff = old column_0 |>> 16 & 0xff
|
|
column_3 |>> 8 & 0xff = old column_1 |>> 8 & 0xff
|
|
column_3 & 0xff = old column_2 & 0xff
|
|
end
|
|
|
|
add_round_key (schedule_index: INTEGER)
|
|
do
|
|
column_0 := column_0.bit_xor (key_schedule [schedule_index])
|
|
column_1 := column_1.bit_xor (key_schedule [schedule_index + 1])
|
|
column_2 := column_2.bit_xor (key_schedule [schedule_index + 2])
|
|
column_3 := column_3.bit_xor (key_schedule [schedule_index + 3])
|
|
end
|
|
|
|
feature -- GF(2^8) arithmetic
|
|
add (one: INTEGER two: INTEGER): INTEGER
|
|
do
|
|
result := one.bit_xor (two)
|
|
end
|
|
|
|
multiply_and_reduce (field: NATURAL_8 multiplier: NATURAL_8): NATURAL_8
|
|
local
|
|
field_expanded: NATURAL_32
|
|
do
|
|
field_expanded := multiply (field, multiplier)
|
|
result := reduce (field_expanded)
|
|
end
|
|
|
|
multiply (field: NATURAL_8 multiplier: NATURAL_8): NATURAL_32
|
|
local
|
|
counter: INTEGER
|
|
field_expanded: NATURAL_32
|
|
do
|
|
field_expanded := field
|
|
from
|
|
counter := 0
|
|
until
|
|
counter > 7
|
|
loop
|
|
if
|
|
multiplier.bit_test (counter)
|
|
then
|
|
result := result.bit_xor (field_expanded.bit_shift_left (counter))
|
|
end
|
|
counter := counter + 1
|
|
end
|
|
end
|
|
|
|
reduce (in: NATURAL_32): NATURAL_8
|
|
local
|
|
counter: INTEGER
|
|
result_expanded: NATURAL_32
|
|
do
|
|
from
|
|
counter := 31
|
|
result_expanded := in
|
|
until
|
|
counter = 7
|
|
loop
|
|
if
|
|
result_expanded.bit_test (counter)
|
|
then
|
|
result_expanded := result_expanded.bit_xor (reducer.bit_shift_right (31 - counter))
|
|
end
|
|
counter := counter - 1
|
|
end
|
|
check
|
|
result_expanded <= result.max_value
|
|
end
|
|
result := result_expanded.to_natural_8
|
|
end
|
|
|
|
s_box (in: NATURAL_8): NATURAL_8
|
|
do
|
|
result := s [in.to_integer_32]
|
|
end
|
|
|
|
two_table: SPECIAL [NATURAL_8]
|
|
-- Table of {02} * x in GF(2^8)
|
|
|
|
three_table: SPECIAL [NATURAL_8]
|
|
-- Table of {03} * x in GF(2^8)
|
|
|
|
nine_table: SPECIAL [NATURAL_8]
|
|
-- Table of {09} * x in GF(2^8)
|
|
|
|
eleven_table: SPECIAL [NATURAL_8]
|
|
-- Table of {0b} * x in GF(2^8)
|
|
|
|
thirteen_table: SPECIAL [NATURAL_8]
|
|
-- Table of {0d} * x in GF(2^8)
|
|
|
|
fourteen_table: SPECIAL [NATURAL_8]
|
|
-- Table of {0E} * x in GF(2^8)
|
|
|
|
multiply_table (multiplier: NATURAL_8): SPECIAL [NATURAL_8]
|
|
local
|
|
counter: INTEGER
|
|
do
|
|
create result.make_filled (0, 256)
|
|
from
|
|
counter := 0
|
|
until
|
|
counter = 256
|
|
loop
|
|
result [counter] := multiply_and_reduce (counter.to_natural_8, multiplier)
|
|
counter := counter + 1
|
|
variant
|
|
256 - counter + 1
|
|
end
|
|
end
|
|
|
|
reducer: NATURAL_32 = 0x8d800000
|
|
|
|
feature {NONE}
|
|
byte_sink (in: NATURAL_8)
|
|
do
|
|
do_nothing
|
|
end
|
|
|
|
key_schedule: SPECIAL [NATURAL_32]
|
|
deferred
|
|
end
|
|
end
|