瀏覽代碼

More cleanup.

Martijn Laan 1 月之前
父節點
當前提交
383e528c7d

+ 1 - 1
Projects/SetupLdr.dpr

@@ -432,7 +432,7 @@ begin
         Reader := TCompressedBlockReader.Create(SourceF, TLZMA1SmallDecompressor);
         try
           if SetupEncryptionHeader.EncryptionUse = euFull then
-            Reader.InitDecryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, -2);
+            Reader.InitDecryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, sccCompressedBlocks1);
 
           SECompressedBlockRead(Reader, SetupHeader, SizeOf(SetupHeader),
             SetupHeaderStrings, SetupHeaderAnsiStrings);

+ 2 - 12
Projects/Src/Compiler.CompressionHandler.pas

@@ -62,7 +62,7 @@ type
 implementation
 
 uses
-  SysUtils, Compiler.Messages, Compiler.HelperFunc;
+  SysUtils, Shared.EncryptionFunc, Compiler.Messages, Compiler.HelperFunc;
 
 constructor TCompressionHandler.Create(ACompiler: TSetupCompiler;
   const InitialSliceFilename: String);
@@ -189,16 +189,6 @@ procedure TCompressionHandler.NewChunk(const ACompressorClass: TCustomCompressor
     end;
   end;
 
-  procedure InitEncryption;
-  begin
-    { Create a unique nonce from the base nonce }
-    var Nonce := FCompiler.GetEncryptionBaseNonce;
-    Nonce.RandomXorStartOffset := Nonce.RandomXorStartOffset xor FChunkStartOffset;
-    Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor FChunkFirstSlice;
-
-    XChaCha20Init(FCryptContext, ACryptKey[0], Length(ACryptKey), Nonce, SizeOf(Nonce), 0);
-  end;
-
 var
   MinBytesLeft: Cardinal;
 begin
@@ -223,7 +213,7 @@ begin
 
   FChunkEncrypted := AUseEncryption;
   if AUseEncryption then
-    InitEncryption;
+    InitCryptContext(ACryptKey, FCompiler.GetEncryptionBaseNonce, FChunkStartOffset, FChunkFirstSlice, FCryptContext);
 
   FChunkStarted := True;
 end;

+ 2 - 17
Projects/Src/Compiler.SetupCompiler.pas

@@ -6922,7 +6922,7 @@ var
       InternalCompressProps);
     try
       if SetupEncryptionHeader.EncryptionUse = euFull then
-        W.InitEncryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, -2);
+        W.InitEncryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, sccCompressedBlocks1);
 
       SECompressedBlockWrite(W, SetupHeader, SizeOf(SetupHeader),
         SetupHeaderStrings, SetupHeaderAnsiStrings);
@@ -7001,7 +7001,7 @@ var
         FileLocationEntries be a fixed size, so don't compress them }
     try
       if SetupEncryptionHeader.EncryptionUse = euFull then
-        W.InitEncryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, -3);
+        W.InitEncryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, sccCompressedBlocks2);
       for J := 0 to FileLocationEntries.Count-1 do
         W.Write(FileLocationEntries[J]^, SizeOf(TSetupFileLocationEntry));
       W.Finish;
@@ -7661,21 +7661,6 @@ var
     GenerateRandomBytes(Nonce, SizeOf(Nonce));
   end;
 
-  { This function assumes EncryptionKey is based on the password }
-  procedure GeneratePasswordTest(const EncryptionKey: TSetupEncryptionKey;
-    const EncryptionBaseNonce: TSetupEncryptionNonce; out PasswordTest: Integer);
-  begin
-    { Create a special nonce that cannot collide with encrypted-file nonces }
-    var Nonce := EncryptionBaseNonce;
-    Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor -1;
-
-    { Encrypt a value of 0 so Setup can do same and compare the results to test the password }
-    var Context: TChaCha20Context;
-    XChaCha20Init(Context, EncryptionKey[0], Length(EncryptionKey), Nonce, SizeOf(Nonce), 0);
-    PasswordTest := 0;
-    XChaCha20Crypt(Context, PasswordTest, PasswordTest, SizeOf(PasswordTest));
-  end;
-
 const
   BadFilePathChars = '/*?"<>|';
   BadFileNameChars = BadFilePathChars + ':';

+ 7 - 20
Projects/Src/Compression.Base.pas

@@ -12,7 +12,7 @@ unit Compression.Base;
 interface
 
 uses
-  Windows, SysUtils, ChaCha20, Shared.Int64Em, Shared.FileClass, Shared.Struct;
+  Windows, SysUtils, ChaCha20, Shared.Int64Em, Shared.FileClass, Shared.Struct, Shared.EncryptionFunc;
 
 type
   ECompressError = class(Exception);
@@ -87,7 +87,7 @@ type
       CompressionLevel: Integer; ACompressorProps: TCompressorProps);
     destructor Destroy; override;
     procedure InitEncryption(const CryptKey: TSetupEncryptionKey;
-      const EncryptionBaseNonce: TSetupEncryptionNonce; const UniqueIndex: Integer);
+      const EncryptionBaseNonce: TSetupEncryptionNonce; const SpecialCryptContextType: TSpecialCryptContextType);
     procedure Finish;
     procedure Write(const Buffer; Count: Cardinal);
   end;
@@ -109,7 +109,7 @@ type
     constructor Create(AFile: TFile; ADecompressorClass: TCustomDecompressorClass);
     destructor Destroy; override;
     procedure InitDecryption(const CryptKey: TSetupEncryptionKey;
-      const EncryptionBaseNonce: TSetupEncryptionNonce; const UniqueIndex: Integer);
+      const EncryptionBaseNonce: TSetupEncryptionNonce; const SpecialCryptContextType: TSpecialCryptContextType);
     procedure Read(var Buffer; Count: Cardinal);
   end;
 
@@ -290,19 +290,6 @@ procedure TStoredDecompressor.Reset;
 begin
 end;
 
-{ TCompressedBlockWriter & Reader }
-
-procedure InitCryptContext(const CryptKey: TSetupEncryptionKey;
-  const EncryptionBaseNonce: TSetupEncryptionNonce; const UniqueIndex: Integer;
-  var CryptContext: TChaCha20Context);
-begin
-  { Recreate the unique nonce from the base nonce }
-  var Nonce := EncryptionBaseNonce;
-  Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor UniqueIndex;
-
-  XChaCha20Init(CryptContext, CryptKey[0], Length(CryptKey), Nonce, SizeOf(Nonce), 0);
-end;
-
 { TCompressedBlockWriter }
 
 type
@@ -341,9 +328,9 @@ begin
 end;
 
 procedure TCompressedBlockWriter.InitEncryption(const CryptKey: TSetupEncryptionKey;
-  const EncryptionBaseNonce: TSetupEncryptionNonce; const UniqueIndex: Integer);
+  const EncryptionBaseNonce: TSetupEncryptionNonce; const SpecialCryptContextType: TSpecialCryptContextType);
 begin
-  InitCryptContext(CryptKey, EncryptionBaseNonce, UniqueIndex, FCryptContext);
+  InitCryptContext(CryptKey, EncryptionBaseNonce, SpecialCryptContextType, FCryptContext);
   FEncrypt := True;
 end;
 
@@ -482,9 +469,9 @@ begin
 end;
 
 procedure TCompressedBlockReader.InitDecryption(const CryptKey: TSetupEncryptionKey;
-  const EncryptionBaseNonce: TSetupEncryptionNonce; const UniqueIndex: Integer);
+  const EncryptionBaseNonce: TSetupEncryptionNonce; const SpecialCryptContextType: TSpecialCryptContextType);
 begin
-  InitCryptContext(CryptKey, EncryptionBaseNonce, UniqueIndex, FCryptContext);
+  InitCryptContext(CryptKey, EncryptionBaseNonce, SpecialCryptContextType, FCryptContext);
   FDecrypt := True;
 end;
 

+ 2 - 2
Projects/Src/Setup.MainFunc.pas

@@ -3117,7 +3117,7 @@ begin
       var Reader := TCompressedBlockReader.Create(SetupFile, TLZMA1Decompressor);
       try
         if SetupEncryptionHeader.EncryptionUse = euFull then
-          Reader.InitDecryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, -2);
+          Reader.InitDecryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, sccCompressedBlocks1);
 
         { Header }
         SECompressedBlockRead(Reader, SetupHeader, SizeOf(SetupHeader),
@@ -3276,7 +3276,7 @@ begin
       Reader := TCompressedBlockReader.Create(SetupFile, TLZMA1Decompressor);
       try
         if SetupEncryptionHeader.EncryptionUse = euFull then
-          Reader.InitDecryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, -3);
+          Reader.InitDecryption(CryptKey, SetupEncryptionHeader.EncryptionBaseNonce, sccCompressedBlocks2);
 
         { File location entries }
         ReadEntriesWithoutVersion(Reader, seFileLocation, SetupHeader.NumFileLocationEntries,

+ 47 - 13
Projects/Src/Shared.EncryptionFunc.pas

@@ -6,23 +6,34 @@ unit Shared.EncryptionFunc;
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
 
-  Encryption function used by ISCmplr, Setup, and SetupLdr
+  Encryption functions used by ISCmplr, Setup, and SetupLdr
 }
 
 interface
 
 uses
-  Shared.Struct;
+  ChaCha20, Shared.Struct;
+
+type
+  TSpecialCryptContextType = (sccPasswordTest, sccCompressedBlocks1, sccCompressedBlocks2);
 
 procedure GenerateEncryptionKey(const Password: String; const Salt: TSetupKDFSalt;
   const Iterations: Integer; out Key: TSetupEncryptionKey);
-function TestPassword(const EncryptionKey: TSetupEncryptionKey;
+procedure InitCryptContext(const CryptKey: TSetupEncryptionKey;
+  const EncryptionBaseNonce: TSetupEncryptionNonce; const StartOffset: Int64; const FirstSlice: Int32;
+  out CryptContext: TChaCha20Context); overload;
+procedure InitCryptContext(const CryptKey: TSetupEncryptionKey;
+  const EncryptionBaseNonce: TSetupEncryptionNonce; const Typ: TSpecialCryptContextType;
+  out CryptContext: TChaCha20Context); overload;
+procedure GeneratePasswordTest(const CryptKey: TSetupEncryptionKey;
+  const EncryptionBaseNonce: TSetupEncryptionNonce; out PasswordTest: Integer);
+function TestPassword(const CryptKey: TSetupEncryptionKey;
   const EncryptionBaseNonce: TSetupEncryptionNonce; const ExpectedPasswordTest: Integer): Boolean;
 
 implementation
 
 uses
-  SysUtils, ChaCha20, PBKDF2;
+  SysUtils, PBKDF2;
 
 procedure GenerateEncryptionKey(const Password: String; const Salt: TSetupKDFSalt;
   const Iterations: Integer; out Key: TSetupEncryptionKey);
@@ -36,21 +47,44 @@ begin
   Move(KeyBytes[0], Key[0], KeyLength);
 end;
 
-{ This function assumes EncryptionKey is based on the password }
-function TestPassword(const EncryptionKey: TSetupEncryptionKey;
-  const EncryptionBaseNonce: TSetupEncryptionNonce; const ExpectedPasswordTest: Integer): Boolean;
+procedure InitCryptContext(const CryptKey: TSetupEncryptionKey;
+  const EncryptionBaseNonce: TSetupEncryptionNonce; const StartOffset: Int64; const FirstSlice: Int32;
+  out CryptContext: TChaCha20Context);
 begin
-  { Do same as compiler did in GeneratePasswordTest and compare results }
+  { Create the unique nonce from the base nonce }
   var Nonce := EncryptionBaseNonce;
-  Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor -1;
+  Nonce.RandomXorStartOffset := Nonce.RandomXorStartOffset xor StartOffset;
+  Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor FirstSlice;
+
+  XChaCha20Init(CryptContext, CryptKey[0], Length(CryptKey), Nonce, SizeOf(Nonce), 0);
+end;
+
+procedure InitCryptContext(const CryptKey: TSetupEncryptionKey;
+  const EncryptionBaseNonce: TSetupEncryptionNonce; const Typ: TSpecialCryptContextType;
+  out CryptContext: TChaCha20Context); overload;
+begin
+  const SpecialFirstSlice = -1-(Ord(Typ)-Ord(Low(Typ)));
+  InitCryptContext(CryptKey, EncryptionBaseNonce, 0, SpecialFirstSlice, CryptContext);
+end;
 
+{ This function assumes CryptKey is based on the password }
+procedure GeneratePasswordTest(const CryptKey: TSetupEncryptionKey;
+  const EncryptionBaseNonce: TSetupEncryptionNonce; out PasswordTest: Integer);
+begin
   var Context: TChaCha20Context;
-  XChaCha20Init(Context, EncryptionKey[0], Length(EncryptionKey), Nonce, SizeOf(Nonce), 0);
-  var ActualPasswordTest := 0;
-  XChaCha20Crypt(Context, ActualPasswordTest, ActualPasswordTest, SizeOf(ActualPasswordTest));
+  InitCryptContext(CryptKey, EncryptionBaseNonce, sccPasswordTest, Context);
 
-  Result := ActualPasswordTest = ExpectedPasswordTest;
+  { Encrypt a value of 0 so Setup can do same and compare the results to test the password }
+  PasswordTest := 0;
+  XChaCha20Crypt(Context, PasswordTest, PasswordTest, SizeOf(PasswordTest));
 end;
 
+function TestPassword(const CryptKey: TSetupEncryptionKey;
+  const EncryptionBaseNonce: TSetupEncryptionNonce; const ExpectedPasswordTest: Integer): Boolean;
+begin
+  var ActualPasswordTest: Integer;
+  GeneratePasswordTest(CryptKey, EncryptionBaseNonce, ActualPasswordTest);
+  Result := ActualPasswordTest = ExpectedPasswordTest;
+end;
 
 end.