BSOne.SFC/Tocsg.Lib/VCL/EncLib/AES/aes_seek.inc

151 lines
5.5 KiB
PHP

(*************************************************************************
Include file for AES CTR Seek routines. These routines are in a separate inc
file because they are included in aes_ctr.pas for non-dlls AND in the dll
interface units AES_Intv/AES_Intf. This is done in order to make tests like
@IncProc=@AES_IncMSBPart work without additional overhead in programs using
the dll.
Version Date Author Modification
------- -------- ------- ------------------------------------------
0.10 31.07.10 W.Ehrhardt Initial version
**************************************************************************)
(****** (C) Copyright 2010 Wolfgang Ehrhardt -- see copying_we.txt ******)
{---------------------------------------------------------------------------}
function AES_CTR_Seek({$ifdef CONST}const{$else}var{$endif} iCTR: TAESBlock;
SOL, SOH: longint; var ctx: TAESContext): integer;
{-Setup ctx for random access crypto stream starting at 64 bit offset SOH*2^32+SOL,}
{ SOH >= 0. iCTR is the initial CTR for offset 0, i.e. the same as in AES_CTR_Init.}
var
i,pt: integer;
carry: word;
TC: TAESBlock;
type
TWA4 = packed array[0..3] of longint; {AES block as array of longint}
TBA4 = packed array[0..3] of byte; {AES "word" as array of byte }
begin
{WARNING: CTR mode demands that the same key / iCTR pair is never reused }
{for encryption. This requirement is especially important for the CTR_Seek}
{function. If different data is written to the same position there will be}
{leakage of information about the plaintexts. Therefore CTR_Seek should }
{normally be used for random reads only.}
if SOH < 0 then begin
AES_CTR_Seek := AES_Err_CTR_SeekOffset;
exit;
end
else with ctx do begin
blen := word(SOL) and $0F;
{64 bit shift right (SOH, SOL) 4 bits}
SOL := (SOL shr 4) or ((SOH and $0F) shl 28);
SOH := (SOH shr 4);
{Check if known IncProc}
{$ifdef FPC_ProcVar}
if (IncProc=nil) or (IncProc=@AES_IncMSBFull) then pt := 1
else if IncProc=@AES_IncMSBPart then pt := 2
else if IncProc=@AES_IncLSBFull then pt := 3
else if IncProc=@AES_IncLSBPart then pt := 4
else pt := 0;
{$else}
if (@IncProc=nil) or (@IncProc=@AES_IncMSBFull) then pt := 1
else if @IncProc=@AES_IncMSBPart then pt := 2
else if @IncProc=@AES_IncLSBFull then pt := 3
else if @IncProc=@AES_IncLSBPart then pt := 4
else pt := 0;
{$endif}
IV := iCTR;
if (SOL or SOH) <> 0 then begin
if pt=0 then begin
{No shortcut calculation for user-defined IncProcs. Note: SOH is }
{positive here even if the sign bit of the original SOH was set. }
{The execution of this loop may be very time-consuming because the }
{IncProc is called many times. If the user is able to calculate the}
{value IVo of the iCTR after calling IncProc (offset div 16) times,}
{invoking the function with AES_CTR_Seek(IVo, SOL and 15, 0, ctx) }
{will completely skip the IncProc calculation, but set the correct }
{values for ctx.IV, ctx.buf, and ctx.blen.}
if SOL=0 then dec(SOH);
repeat
repeat
IncProc(IV);
dec(SOL);
until SOL=0;
dec(SOH);
until SOH<=0;
end
else begin
fillchar(TC, sizeof(TC), 0);
carry := 0;
if (pt=1) or (pt=2) then begin
{MSB functions, first fill 128 bit offset vector}
for i:=0 to 3 do begin
TC[15-i] := TBA4(SOL)[i];
TC[11-i] := TBA4(SOH)[i];
end;
{64 bit addition}
for i:=15 downto 8 do begin
carry := carry + TC[i] + IV[i];
IV[i] := carry and $FF;
carry := carry shr 8;
end;
if (pt=1) and (carry<>0) then begin
{"Full" function: propagate carry through remaining bytes}
for i:=7 downto 0 do begin
carry := carry + IV[i];
IV[i] := carry and $FF;
carry := carry shr 8;
{$ifdef CONST}
if carry=0 then break;
{$endif}
end;
end;
end
else begin
{LSB functions, first fill 128 bit offset vector}
TWA4(TC)[0] := SOL;
TWA4(TC)[1] := SOH;
{64 bit addition}
for i:=0 to 7 do begin
carry := carry + TC[i] + IV[i];
IV[i] := carry and $FF;
carry := carry shr 8;
end;
if (pt=3) and (carry<>0) then begin
{"Full" function: propagate carry through remaining bytes}
for i:=8 to 15 do begin
carry := carry + IV[i];
IV[i] := carry and $FF;
carry := carry shr 8;
{$ifdef CONST}
if carry=0 then break;
{$endif}
end;
end;
end;
end;
end;
AES_Encrypt(ctx, IV, buf);
AES_CTR_Seek := 0;
end;
end;
{$ifdef HAS_INT64}
{$ifndef DLL}
{-----------------------------------------------------------------------------}
function AES_CTR_Seek64(const iCTR: TAESBlock; SO: int64; var ctx: TAESContext): integer;
{-Setup ctx for random access crypto stream starting at 64 bit offset SO >= 0;}
{ iCTR is the initial CTR value for offset 0, i.e. the same as in AES_CTR_Init.}
type
LH = packed record L,H: longint; end;
begin
AES_CTR_Seek64 := AES_CTR_Seek(iCTR, LH(SO).L, LH(SO).H, ctx);
end;
{$endif}
{$endif}