Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions Source/DECCipherFormats.pas
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ procedure TDECFormattedCipher.DoEncodeDecodeStream(const Source, Dest: TStream;
const OnProgress: TDECProgressEvent);
var
Buffer: TBytes;
outBuffer: TBytes;
BufferSize, Bytes: Integer;
Max, StartPos, Pos: Int64;
begin
Expand All @@ -737,6 +738,7 @@ procedure TDECFormattedCipher.DoEncodeDecodeStream(const Source, Dest: TStream;
StartPos := Pos;

if DataSize > 0 then
begin
try
if Assigned(OnProgress) then
OnProgress(Max, 0, Started);
Expand All @@ -752,6 +754,11 @@ procedure TDECFormattedCipher.DoEncodeDecodeStream(const Source, Dest: TStream;
SetLength(Buffer, BufferSize)
else
SetLength(Buffer, DataSize);

outBuffer := Buffer;
if (FMode = cmGCM) then
SetLength(outBuffer, Length(Buffer));

while DataSize > 0 do
begin
Bytes := BufferSize;
Expand All @@ -760,8 +767,8 @@ procedure TDECFormattedCipher.DoEncodeDecodeStream(const Source, Dest: TStream;
Source.ReadBuffer(Buffer[0], Bytes);

// The real encryption or decryption routine
CipherProc(Buffer[0], Buffer[0], Bytes);
Dest.WriteBuffer(Buffer[0], Bytes);
CipherProc(Buffer[0], outBuffer[0], Bytes);
Dest.WriteBuffer(outBuffer[0], Bytes);
Dec(DataSize, Bytes);
Inc(Pos, Bytes);

Expand All @@ -770,9 +777,18 @@ procedure TDECFormattedCipher.DoEncodeDecodeStream(const Source, Dest: TStream;
end;
finally
ProtectBytes(Buffer);
if (FMode = cmGCM) then
ProtectBytes(outBuffer);
if Assigned(OnProgress) then
OnProgress(Max, Max, Finished);
end;
end
else
if (FMode = cmGCM) then
begin
Buffer := nil;
CipherProc(Buffer, Buffer, 0);
end;
end;

procedure TDECFormattedCipher.EncodeStream(const Source, Dest: TStream; DataSize: Int64;
Expand Down
153 changes: 152 additions & 1 deletion Unit Tests/Tests/TestDECCipherModesGCM.pas
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ TestTDECGCM = class(TTestCase)
published
procedure TestEncode;
procedure TestDecode;
procedure TestDecodeStream;
procedure TestDecodeAuthenticationFailure;
procedure TestEncodeStream;
procedure TestSetGetDataToAuthenticate;
procedure TestSetGetAuthenticationBitLength;
procedure TestGetStandardAuthenticationTagBitLengths;
Expand Down Expand Up @@ -472,7 +474,9 @@ procedure TestTDECGCM.TestDecode;
BytesOf(TestDataSet.TestData[i].CT)));
FCipherAES.Done;
except
self.Status('CryptKey ' + string(TestDataSet.TestData[i].CryptKey));
on E: Exception do
Status('CryptKey ' + string(TestDataSet.TestData[i].CryptKey) +
' ' + E.ClassName + ': ' + E.Message);
end;

CheckEquals(string(TestDataSet.TestData[i].PT),
Expand Down Expand Up @@ -631,6 +635,153 @@ function TestTDECGCM.IsEqual(const a, b : TBytes):Boolean;
Result := true;
end;

procedure TestTDECGCM.TestDecodeStream;
var
ctbStream: TBytesStream;
ctBytes: TBytes;
TestDataSet : TGCMTestSetEntry;
i : Integer;
DecryptData : TBytes;
ptbStream: TBytesStream;
begin
FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV128.rsp', FTestDataList);
FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV192.rsp', FTestDataList);
FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV256.rsp', FTestDataList);

for TestDataSet in FTestDataList do
begin
for i := Low(TestDataSet.TestData) to High(TestDataSet.TestData) do
begin
ctBytes := TFormat_HexL.Decode(BytesOf(TestDataSet.TestData[i].CT));

try


FCipherAES.Init(BytesOf(TFormat_HexL.Decode(TestDataSet.TestData[i].CryptKey)),
BytesOf(TFormat_HexL.Decode(TestDataSet.TestData[i].InitVector)),
$FF);

FCipherAES.AuthenticationResultBitLength := TestDataSet.Taglen;
FCipherAES.DataToAuthenticate := TFormat_HexL.Decode(
BytesOf(
TestDataSet.TestData[i].AAD));

FCipherAES.ExpectedAuthenticationResult :=
TFormat_HexL.Decode(BytesOf(TestDataSet.TestData[i].TagResult));

ctbStream := TBytesStream.Create(ctBytes);
ptbStream := TBytesStream.Create;

FCipherAES.DecodeStream(ctbStream, ptbStream, ctbStream.Size);

FCipherAES.Done;

DecryptData := ptbStream.Bytes;
SetLength(DecryptData, ptbStream.Size);

except
on E: Exception do
Status('CryptKey ' + string(TestDataSet.TestData[i].CryptKey) +
' ' + E.ClassName + ': ' + E.Message);
end;
FreeAndNil(ptbStream);
FreeAndNil(ctbStream);

CheckEquals(string(TestDataSet.TestData[i].PT),
StringOf(TFormat_HexL.Encode(DecryptData)),
'Plaintext wrong for key ' +
string(TestDataSet.TestData[i].CryptKey) + ' IV ' +
string(TestDataSet.TestData[i].InitVector) + ' PT ' +
string(TestDataSet.TestData[i].PT) + ' AAD ' +
string(TestDataSet.TestData[i].AAD) + ' Exp.: ' +
string(TestDataSet.TestData[i].CT) + ' Act.: ' +
StringOf(TFormat_HexL.Encode(DecryptData)));

// Additional Authentication Data pr�fen
CheckEquals(string(TestDataSet.TestData[i].TagResult),
StringOf(TFormat_HexL.Encode(FCipherAES.CalculatedAuthenticationResult)),
'Authentication tag wrong for key ' +
string(TestDataSet.TestData[i].CryptKey) + ' IV ' +
string(TestDataSet.TestData[i].InitVector) + ' PT ' +
string(TestDataSet.TestData[i].PT) + ' AAD ' +
string(TestDataSet.TestData[i].AAD) + ' Exp.: ' +
string(TestDataSet.TestData[i].TagResult) + ' Act.: ' +
StringOf(TFormat_HexL.Encode(FCipherAES.DataToAuthenticate)));

end;
end;
end;

procedure TestTDECGCM.TestEncodeStream;
var
ctbStream: TBytesStream;
ptBytes: TBytes;
TestDataSet : TGCMTestSetEntry;
i : Integer;
EncryptData : TBytes;
ptbStream: TBytesStream;
begin
FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV128.rsp', FTestDataList);
FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV192.rsp', FTestDataList);
FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV256.rsp', FTestDataList);

for TestDataSet in FTestDataList do
begin
for i := Low(TestDataSet.TestData) to High(TestDataSet.TestData) do
begin
ptBytes := TFormat_HexL.Decode(BytesOf(TestDataSet.TestData[i].PT));

FCipherAES.Init(BytesOf(TFormat_HexL.Decode(TestDataSet.TestData[i].CryptKey)),
BytesOf(TFormat_HexL.Decode(TestDataSet.TestData[i].InitVector)),
$FF);

FCipherAES.AuthenticationResultBitLength := TestDataSet.Taglen;
FCipherAES.DataToAuthenticate := TFormat_HexL.Decode(
BytesOf(
TestDataSet.TestData[i].AAD));

ptbStream := TBytesStream.Create(ptBytes);
ctbStream := TBytesStream.Create;
try
FCipherAES.EncodeStream(ptbStream, ctbStream, ptbStream.Size);

FCipherAES.Done;

EncryptData := ctbStream.Bytes;
SetLength(EncryptData, ctbStream.Size);
except
on E: Exception do
Status('CryptKey ' + string(TestDataSet.TestData[i].CryptKey) +
' ' + E.ClassName + ': ' + E.Message);
end;

FreeAndNil(ptbStream);
FreeAndNil(ctbStream);

CheckEquals(string(TestDataSet.TestData[i].CT),
StringOf(TFormat_HexL.Encode(EncryptData)),
'Cipher text wrong for Key ' +
string(TestDataSet.TestData[i].CryptKey) + ' IV ' +
string(TestDataSet.TestData[i].InitVector) + ' PT ' +
string(TestDataSet.TestData[i].PT) + ' AAD ' +
string(TestDataSet.TestData[i].AAD) + ' Exp.: ' +
string(TestDataSet.TestData[i].CT) + ' Act.: ' +
StringOf(TFormat_HexL.Encode(EncryptData)));

// Additional Authentication Data pr�fen
CheckEquals(string(TestDataSet.TestData[i].TagResult),
StringOf(TFormat_HexL.Encode(FCipherAES.CalculatedAuthenticationResult)),
'Authentication tag wrong for Key ' +
string(TestDataSet.TestData[i].CryptKey) + ' IV ' +
string(TestDataSet.TestData[i].InitVector) + ' PT ' +
string(TestDataSet.TestData[i].PT) + ' AAD ' +
string(TestDataSet.TestData[i].AAD) + ' Exp.: ' +
string(TestDataSet.TestData[i].TagResult) + ' Act.: ' +
StringOf(TFormat_HexL.Encode(FCipherAES.DataToAuthenticate)));
end;
end;
end;

procedure TestTDECGCM.TestGetStandardAuthenticationTagBitLengths;
var
BitLengths: TStandardBitLengths;
Expand Down