DelphiEncryptionCompendium
DelphiEncryptionCompendium copied to clipboard
Access violation if GCM mode is set after cipher is initialized
To Reproduce
- Open demo project Cipher_Console
- Change Cipher.Mode to cmGCM
- Run the code. You receive EAccessViolation
Usually, if you change the cipher mode after the cipher has been initialized, then TDECCipher.SetMode
should call Done
on the cipher and re-initialize it.
GCM Encode requires that TGCM.Init
is called and has set FEncryptionMethod := EncryptionMethod
. However, if Ciper.Mode
is set after the cipher has been initialized, then TGCM
is created but TGCM.Init
has not been called.
procedure TDECCipherModes.InitMode;
begin
if FMode = TCipherMode.cmGCM then
begin
if Context.BlockSize = 16 then
FGCM := TGCM.Create
else
// GCM requires a cipher with 128 bit block size
raise EDECCipherException.CreateResFmt(@sInvalidBlockSize,
[128, GetEnumName(TypeInfo(TCipherMode),
Integer(FMode))]);
end
else
if Assigned(FGCM) then
FreeAndNil(FGCM);
end;
The program flow if Mode has been set before init:
- TDECCipher.Init()
- TDECCipher.Init()
- TDECCipherModes.OnAfterInitVectorInitialized ( calls
FGCM.Init(self.DoEncode, OriginalInitVector)
) - TGCM.Init
The program flow if Mode has been set after init:
- TDECCipher.SetMode
- TDECCipherModes.InitMode
- TGCM.Create, but not TGCM.Init ( I am not sure where I get
OriginalInitVector
from )
So... what do we do? We probably need to preserve the InitVector, so we can call TGCM.Init with the correct parameters.
The other solution is to forbid to change the mode after the cipher has been initialized. But this is a code breaking change.