|
@@ -19,7 +19,7 @@ interface
|
|
|
|
|
|
uses
|
|
uses
|
|
Windows, SysUtils, Classes, Generics.Collections,
|
|
Windows, SysUtils, Classes, Generics.Collections,
|
|
- SimpleExpression, SHA256,
|
|
|
|
|
|
+ SimpleExpression, SHA256, ChaCha20,
|
|
Shared.Struct, Shared.CompilerInt, Shared.PreprocInt, Shared.SetupMessageIDs,
|
|
Shared.Struct, Shared.CompilerInt, Shared.PreprocInt, Shared.SetupMessageIDs,
|
|
Shared.SetupSectionDirectives, Shared.VerInfoFunc, Shared.Int64Em, Shared.DebugStruct,
|
|
Shared.SetupSectionDirectives, Shared.VerInfoFunc, Shared.Int64Em, Shared.DebugStruct,
|
|
Compiler.ScriptCompiler, Compiler.StringLists, Compression.LZMACompressor;
|
|
Compiler.ScriptCompiler, Compiler.StringLists, Compression.LZMACompressor;
|
|
@@ -111,7 +111,7 @@ type
|
|
InternalCompressProps, CompressProps: TLZMACompressorProps;
|
|
InternalCompressProps, CompressProps: TLZMACompressorProps;
|
|
UseSolidCompression: Boolean;
|
|
UseSolidCompression: Boolean;
|
|
DontMergeDuplicateFiles: Boolean;
|
|
DontMergeDuplicateFiles: Boolean;
|
|
- CryptKey: String;
|
|
|
|
|
|
+ CryptKey: TSHA256Digest;
|
|
TimeStampsInUTC: Boolean;
|
|
TimeStampsInUTC: Boolean;
|
|
TimeStampRounding: Integer;
|
|
TimeStampRounding: Integer;
|
|
TouchDateOption: (tdCurrent, tdNone, tdExplicit);
|
|
TouchDateOption: (tdCurrent, tdNone, tdExplicit);
|
|
@@ -271,7 +271,7 @@ type
|
|
function GetDebugInfo: TMemoryStream;
|
|
function GetDebugInfo: TMemoryStream;
|
|
function GetDiskSliceSize:Longint;
|
|
function GetDiskSliceSize:Longint;
|
|
function GetDiskSpanning: Boolean;
|
|
function GetDiskSpanning: Boolean;
|
|
- function GetEncryptionBaseNonce: TSetupNonce;
|
|
|
|
|
|
+ function GetEncryptionBaseNonce: TSetupEncryptionNonce;
|
|
function GetExeFilename: String;
|
|
function GetExeFilename: String;
|
|
function GetLineFilename: String;
|
|
function GetLineFilename: String;
|
|
function GetLineNumber: Integer;
|
|
function GetLineNumber: Integer;
|
|
@@ -597,7 +597,7 @@ begin
|
|
Result := DiskSpanning;
|
|
Result := DiskSpanning;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TSetupCompiler.GetEncryptionBaseNonce: TSetupNonce;
|
|
|
|
|
|
+function TSetupCompiler.GetEncryptionBaseNonce: TSetupEncryptionNonce;
|
|
begin
|
|
begin
|
|
Result := SetupHeader.EncryptionBaseNonce;
|
|
Result := SetupHeader.EncryptionBaseNonce;
|
|
end;
|
|
end;
|
|
@@ -2350,29 +2350,31 @@ var
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure GeneratePasswordHashAndSalt(const Password: String;
|
|
|
|
- var Hash: TSHA256Digest; var Salt: TSetupSalt);
|
|
|
|
- var
|
|
|
|
- Context: TSHA256Context;
|
|
|
|
- begin
|
|
|
|
- { Random salt is mixed into the password hash to make it more difficult
|
|
|
|
- for someone to tell that two installations use the same password. A
|
|
|
|
- fixed string is also mixed in "just in case" the system's RNG is
|
|
|
|
- broken -- this hash must never be the same as the hash used for
|
|
|
|
- encryption. }
|
|
|
|
- GenerateRandomBytes(Salt, SizeOf(Salt));
|
|
|
|
- SHA256Init(Context);
|
|
|
|
- SHA256Update(Context, PAnsiChar('PasswordCheckHash')^, Length('PasswordCheckHash'));
|
|
|
|
- SHA256Update(Context, Salt, SizeOf(Salt));
|
|
|
|
- SHA256Update(Context, Pointer(Password)^, Length(Password)*SizeOf(Password[1]));
|
|
|
|
- Hash := SHA256Final(Context);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- procedure GenerateEncryptionBaseNonce(var Nonce: TSetupNonce);
|
|
|
|
|
|
+ procedure GenerateEncryptionBaseNonce(var Nonce: TSetupEncryptionNonce);
|
|
begin
|
|
begin
|
|
GenerateRandomBytes(Nonce, SizeOf(Nonce));
|
|
GenerateRandomBytes(Nonce, SizeOf(Nonce));
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+ procedure GenerateEncryptionKey(const Password: String; var Key: TSetupEncryptionKey);
|
|
|
|
+ begin
|
|
|
|
+ Key := SHA256Buf(Pointer(Password)^, Length(Password)*SizeOf(Password[1]))
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ { This function assumes EncryptionKey is based on the password }
|
|
|
|
+ procedure GeneratePasswordTest(const EncryptionKey: TSetupEncryptionKey;
|
|
|
|
+ const EncryptionBaseNonce: TSetupEncryptionNonce; var 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;
|
|
|
|
+
|
|
procedure StrToTouchDate(const S: String);
|
|
procedure StrToTouchDate(const S: String);
|
|
var
|
|
var
|
|
P: PChar;
|
|
P: PChar;
|
|
@@ -2813,11 +2815,8 @@ begin
|
|
ssEnableDirDoesntExistWarning: begin
|
|
ssEnableDirDoesntExistWarning: begin
|
|
SetSetupHeaderOption(shEnableDirDoesntExistWarning);
|
|
SetSetupHeaderOption(shEnableDirDoesntExistWarning);
|
|
end;
|
|
end;
|
|
- ssEncryption:
|
|
|
|
- begin
|
|
|
|
|
|
+ ssEncryption: begin
|
|
SetSetupHeaderOption(shEncryptionUsed);
|
|
SetSetupHeaderOption(shEncryptionUsed);
|
|
- if shEncryptionUsed in SetupHeader.Options then
|
|
|
|
- GenerateEncryptionBaseNonce(SetupHeader.EncryptionBaseNonce);
|
|
|
|
end;
|
|
end;
|
|
ssExtraDiskSpaceRequired: begin
|
|
ssExtraDiskSpaceRequired: begin
|
|
if not StrToInteger64(Value, SetupHeader.ExtraDiskSpaceRequired) then
|
|
if not StrToInteger64(Value, SetupHeader.ExtraDiskSpaceRequired) then
|
|
@@ -2929,9 +2928,9 @@ begin
|
|
end;
|
|
end;
|
|
ssPassword: begin
|
|
ssPassword: begin
|
|
if Value <> '' then begin
|
|
if Value <> '' then begin
|
|
- CryptKey := Value;
|
|
|
|
- GeneratePasswordHashAndSalt(Value, SetupHeader.PasswordHash,
|
|
|
|
- SetupHeader.PasswordSalt);
|
|
|
|
|
|
+ GenerateEncryptionBaseNonce(SetupHeader.EncryptionBaseNonce);
|
|
|
|
+ GenerateEncryptionKey(Value, CryptKey);
|
|
|
|
+ GeneratePasswordTest(CryptKey, SetupHeader.EncryptionBaseNonce, SetupHeader.PasswordTest);
|
|
Include(SetupHeader.Options, shPassword);
|
|
Include(SetupHeader.Options, shPassword);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -7559,7 +7558,7 @@ begin
|
|
else
|
|
else
|
|
VersionInfoProductTextVersion := VersionInfoProductVersionOriginalValue;
|
|
VersionInfoProductTextVersion := VersionInfoProductVersionOriginalValue;
|
|
end;
|
|
end;
|
|
- if (shEncryptionUsed in SetupHeader.Options) and (CryptKey = '') then begin
|
|
|
|
|
|
+ if (shEncryptionUsed in SetupHeader.Options) and not (shPassword in SetupHeader.Options) then begin
|
|
LineNumber := SetupDirectiveLines[ssEncryption];
|
|
LineNumber := SetupDirectiveLines[ssEncryption];
|
|
AbortCompileFmt(SCompilerEntryMissing2, ['Setup', 'Password']);
|
|
AbortCompileFmt(SCompilerEntryMissing2, ['Setup', 'Password']);
|
|
end;
|
|
end;
|