An implementation of the block cipher LEA-256 for Embarcadero Delphi
unit LEA256;
{
An implementation of the block cipher LEA-256 (Lightweight Encryption Algorithm 256-bit) for Embarcadero Delphi.
Original Author: Andreas Jonsson. (www.andreas-software.com)
NOTICE: YOU MAY USE AND MODIFY THIS SOURCE CODE FREELY, THE ONLY REQUIREMENT IS THAT THE COMMENT ABOUT THE ORIGINAL AUTHOR AND THIS NOTICE REMAINS IN THE SOURCE CODE.
}
interface
uses
System.SysUtils, System.Variants, System.Classes;
type
TLEA256Constants = array[0..7] of Cardinal;
const LEA256Constants: TLEA256Constants = ($C3EFE9DB, $44626B02, $79E27C8A, $78DF30EC, $715EA49E, $C785DA0A, $E04EF22A, $E5C40957);
type
TLEA256Keys = array[0..7] of Cardinal;
type
TLEA256RoundKeys = array[0..31] of array[0..5] of Cardinal;
type
TLEA256Block = array[0..3] of Cardinal;
type
TLEA256Context = record
RoundKeys: TLEA256RoundKeys;
end;
function ROL32(Value: Cardinal; N: Cardinal): Cardinal; inline;
function ROR32(Value: Cardinal; N: Cardinal): Cardinal; inline;
procedure LEA256_KeySchedule(var Context: TLEA256Context; Keys: TLEA256Keys);
procedure LEA256_Initialize(var Context: TLEA256Context; Keys: TLEA256Keys);
procedure LEA256_Burn(var Context: TLEA256Context);
procedure LEA256_Encrypt(var Context: TLEA256Context; var Block: TLEA256Block);
procedure LEA256_Decrypt(var Context: TLEA256Context; var Block: TLEA256Block);
implementation
function ROL32(Value: Cardinal; N: Cardinal): Cardinal; inline;
begin
Result := ((Value shl N) or (Value shr (32 - N)));
end;
function ROR32(Value: Cardinal; N: Cardinal): Cardinal; inline;
begin
Result := ((Value shr N) or (Value shl (32 - N)));
end;
procedure LEA256_KeySchedule(var Context: TLEA256Context; Keys: TLEA256Keys);
var T: TLEA256Keys;
var I: Integer;
var Temp: Cardinal;
begin
T := Keys;
for I := 0 to 31 do begin
Temp := ROL32(LEA256Constants[I and 7], I and $1F);
T[((I * 6) + 0) and 7] := ROL32(T[((I * 6) + 0) and 7] + Temp , 1);
T[((I * 6) + 1) and 7] := ROL32(T[((I * 6) + 1) and 7] + ROL32(Temp, 1), 3);
T[((I * 6) + 2) and 7] := ROL32(T[((I * 6) + 2) and 7] + ROL32(Temp, 2), 6);
T[((I * 6) + 3) and 7] := ROL32(T[((I * 6) + 3) and 7] + ROL32(Temp, 3), 11);
T[((I * 6) + 4) and 7] := ROL32(T[((I * 6) + 4) and 7] + ROL32(Temp, 4), 13);
T[((I * 6) + 5) and 7] := ROL32(T[((I * 6) + 5) and 7] + ROL32(Temp, 5), 17);
Context.RoundKeys[I][0] := T[((I * 6) + 0) and 7];
Context.RoundKeys[I][1] := T[((I * 6) + 1) and 7];
Context.RoundKeys[I][2] := T[((I * 6) + 2) and 7];
Context.RoundKeys[I][3] := T[((I * 6) + 3) and 7];
Context.RoundKeys[I][4] := T[((I * 6) + 4) and 7];
Context.RoundKeys[I][5] := T[((I * 6) + 5) and 7];
end;
end;
procedure LEA256_Initialize(var Context: TLEA256Context; Keys: TLEA256Keys);
begin
LEA256_KeySchedule(Context, Keys);
end;
procedure LEA256_Burn(var Context: TLEA256Context);
var I: Integer;
var J: Integer;
begin
for I := 0 to 31 do begin
for J := 0 to 5 do begin
Context.RoundKeys[I][J] := 0;
end;
end;
end;
procedure LEA256_Encrypt(var Context: TLEA256Context; var Block: TLEA256Block);
var I: Integer;
begin
I := -1;
repeat
I := I + 1;
Block[3] := ROR32((Block[2] xor Context.RoundKeys[I][4]) + (Block[3] xor Context.RoundKeys[I][5]), 3);
Block[2] := ROR32((Block[1] xor Context.RoundKeys[I][2]) + (Block[2] xor Context.RoundKeys[I][3]), 5);
Block[1] := ROL32((Block[0] xor Context.RoundKeys[I][0]) + (Block[1] xor Context.RoundKeys[I][1]), 9);
I := I + 1;
Block[0] := ROR32((Block[3] xor Context.RoundKeys[I][4]) + (Block[0] xor Context.RoundKeys[I][5]), 3);
Block[3] := ROR32((Block[2] xor Context.RoundKeys[I][2]) + (Block[3] xor Context.RoundKeys[I][3]), 5);
Block[2] := ROL32((Block[1] xor Context.RoundKeys[I][0]) + (Block[2] xor Context.RoundKeys[I][1]), 9);
I := I + 1;
Block[1] := ROR32((Block[0] xor Context.RoundKeys[I][4]) + (Block[1] xor Context.RoundKeys[I][5]), 3);
Block[0] := ROR32((Block[3] xor Context.RoundKeys[I][2]) + (Block[0] xor Context.RoundKeys[I][3]), 5);
Block[3] := ROL32((Block[2] xor Context.RoundKeys[I][0]) + (Block[3] xor Context.RoundKeys[I][1]), 9);
I := I + 1;
Block[2] := ROR32((Block[1] xor Context.RoundKeys[I][4]) + (Block[2] xor Context.RoundKeys[I][5]), 3);
Block[1] := ROR32((Block[0] xor Context.RoundKeys[I][2]) + (Block[1] xor Context.RoundKeys[I][3]), 5);
Block[0] := ROL32((Block[3] xor Context.RoundKeys[I][0]) + (Block[0] xor Context.RoundKeys[I][1]), 9);
until (I = 31);
end;
procedure LEA256_Decrypt(var Context: TLEA256Context; var Block: TLEA256Block);
var I: Integer;
begin
I := 31;
repeat
Block[0] := (ROR32(Block[0], 9) - (Block[3] xor Context.RoundKeys[I][0])) xor Context.RoundKeys[I][1];
Block[1] := (ROL32(Block[1], 5) - (Block[0] xor Context.RoundKeys[I][2])) xor Context.RoundKeys[I][3];
Block[2] := (ROL32(Block[2], 3) - (Block[1] xor Context.RoundKeys[I][4])) xor Context.RoundKeys[I][5];
I := I - 1;
Block[3] := (ROR32(Block[3], 9) - (Block[2] xor Context.RoundKeys[I][0])) xor Context.RoundKeys[I][1];
Block[0] := (ROL32(Block[0], 5) - (Block[3] xor Context.RoundKeys[I][2])) xor Context.RoundKeys[I][3];
Block[1] := (ROL32(Block[1], 3) - (Block[0] xor Context.RoundKeys[I][4])) xor Context.RoundKeys[I][5];
I := I - 1;
Block[2] := (ROR32(Block[2], 9) - (Block[1] xor Context.RoundKeys[I][0])) xor Context.RoundKeys[I][1];
Block[3] := (ROL32(Block[3], 5) - (Block[2] xor Context.RoundKeys[I][2])) xor Context.RoundKeys[I][3];
Block[0] := (ROL32(Block[0], 3) - (Block[3] xor Context.RoundKeys[I][4])) xor Context.RoundKeys[I][5];
I := I - 1;
Block[1] := (ROR32(Block[1], 9) - (Block[0] xor Context.RoundKeys[I][0])) xor Context.RoundKeys[I][1];
Block[2] := (ROL32(Block[2], 5) - (Block[1] xor Context.RoundKeys[I][2])) xor Context.RoundKeys[I][3];
Block[3] := (ROL32(Block[3], 3) - (Block[2] xor Context.RoundKeys[I][4])) xor Context.RoundKeys[I][5];
I := I - 1;
until (I = -1);
end;
end.