瀏覽代碼

Implement the base nonce.

Martijn Laan 1 年之前
父節點
當前提交
db877306fa

+ 5 - 5
Projects/Src/Compiler.CompressionHandler.pas

@@ -193,12 +193,12 @@ procedure TCompressionHandler.NewChunk(const ACompressorClass: TCustomCompressor
     { Create an SHA-256 hash of ACryptKey, and use that as the key }
     var Key := THashSHA2.GetHashBytes(ACryptKey, SHA256);
 
-    { Generate and write a random nonce. }
-    var Nonce: TSetupNonce;
-    GenerateRandomBytes(Nonce, SizeOf(Nonce));
-    FDestFile.WriteBuffer(Nonce, SizeOf(Nonce));
+    { 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, Key[0], Length(Key), Nonce[0], Length(Nonce), 0);
+    XChaCha20Init(FCryptContext, Key[0], Length(Key), Nonce, SizeOf(Nonce), 0);
   end;
 
 var

+ 13 - 0
Projects/Src/Compiler.SetupCompiler.pas

@@ -271,6 +271,7 @@ type
     function GetDebugInfo: TMemoryStream;
     function GetDiskSliceSize:Longint;
     function GetDiskSpanning: Boolean;
+    function GetEncryptionBaseNonce: TSetupNonce;
     function GetExeFilename: String;
     function GetLineFilename: String;
     function GetLineNumber: Integer;
@@ -596,6 +597,11 @@ begin
   Result := DiskSpanning;
 end;
 
+function TSetupCompiler.GetEncryptionBaseNonce: TSetupNonce;
+begin
+  Result := SetupHeader.EncryptionBaseNonce;
+end;
+
 function TSetupCompiler.GetExeFilename: String;
 begin
   Result := ExeFilename;
@@ -2362,6 +2368,11 @@ var
     Hash := SHA1Final(Context);
   end;
 
+  procedure GenerateEncryptionBaseNonce(var Nonce: TSetupNonce);
+  begin
+    GenerateRandomBytes(Nonce, SizeOf(Nonce));
+  end;
+
   procedure StrToTouchDate(const S: String);
   var
     P: PChar;
@@ -2805,6 +2816,8 @@ begin
     ssEncryption:
       begin
         SetSetupHeaderOption(shEncryptionUsed);
+        if shEncryptionUsed in SetupHeader.Options then
+         GenerateEncryptionBaseNonce(SetupHeader.EncryptionBaseNonce);
       end;
     ssExtraDiskSpaceRequired: begin
         if not StrToInteger64(Value, SetupHeader.ExtraDiskSpaceRequired) then

+ 9 - 8
Projects/Src/Setup.FileExtractor.pas

@@ -190,15 +190,15 @@ procedure TFileExtractor.SeekTo(const FL: TSetupFileLocationEntry;
 
   procedure InitDecryption;
   begin
-    { Read the nonce }
-    var Nonce: TSetupNonce;
-    if FSourceF.Read(Nonce, SizeOf(Nonce)) <> SizeOf(Nonce) then
-      SourceIsCorrupted('Failed to read nonce');
-
     { Initialize the key, which is the SHA-256 hash of FCryptKey }
     var Key := THashSHA2.GetHashBytes(FCryptKey, SHA256);
 
-    XChaCha20Init(FCryptContext, Key[0], Length(Key), Nonce[0], Length(Nonce), 0);
+    { Recreate the unique nonce from the base nonce }
+    var Nonce := SetupHeader.EncryptionBaseNonce;
+    Nonce.RandomXorStartOffset := Nonce.RandomXorStartOffset xor FChunkStartOffset;
+    Nonce.RandomXorFirstSlice := Nonce.RandomXorFirstSlice xor FChunkFirstSlice;
+
+    XChaCha20Init(FCryptContext, Key[0], Length(Key), Nonce, SizeOf(Nonce), 0);
   end;
 
   procedure Discard(Count: Integer64);
@@ -253,8 +253,6 @@ begin
         SourceIsCorrupted('Failed to read CompID');
       if Longint(TestCompID) <> Longint(ZLIBID) then
         SourceIsCorrupted('Invalid CompID');
-      if foChunkEncrypted in FL.Flags then
-        InitDecryption;
 
       FChunkFirstSlice := FL.FirstSlice;
       FChunkLastSlice := FL.LastSlice;
@@ -264,6 +262,9 @@ begin
       FChunkDecompressedBytesRead.Lo := 0;
       FChunkCompressed := foChunkCompressed in FL.Flags;
       FChunkEncrypted := foChunkEncrypted in FL.Flags;
+
+      if foChunkEncrypted in FL.Flags then
+        InitDecryption;
     end;
 
     { Need to seek forward in the chunk? }

+ 6 - 1
Projects/Src/Shared.Struct.pas

@@ -69,7 +69,11 @@ type
   TSetupLanguageDetectionMethod = (ldUILanguage, ldLocale, ldNone);
   TSetupCompressMethod = (cmStored, cmZip, cmBzip, cmLZMA, cmLZMA2);
   TSetupSalt = array[0..7] of Byte;
-  TSetupNonce = array[0..23] of Byte;
+  TSetupNonce = record
+    RandomXorStartOffset: Int64;
+    RandomXorFirstSlice: Int32;
+    RemainingRandom: array[0..2] of Int32;
+  end;
   TSetupProcessorArchitecture = (paUnknown, paX86, paX64, paArm32, paArm64);
   TSetupProcessorArchitectures = set of TSetupProcessorArchitecture;
   TSetupDisablePage = (dpAuto, dpNo, dpYes);
@@ -107,6 +111,7 @@ type
     WizardImageAlphaFormat: (afIgnored, afDefined, afPremultiplied); // Must be same as Graphics.TAlphaFormat
     PasswordHash: TSHA1Digest;
     PasswordSalt: TSetupSalt;
+    EncryptionBaseNonce: TSetupNonce;
     ExtraDiskSpaceRequired: Integer64;
     SlicesPerDisk: Integer;
     UninstallLogMode: (lmAppend, lmNew, lmOverwrite);