Browse Source

Merge branch 'main' into 7zdll

Martijn Laan 3 months ago
parent
commit
a28a2f3366

+ 1 - 0
.gitignore

@@ -1,5 +1,6 @@
 /c.bat
 /c.bat
 /compilesettings.bat
 /compilesettings.bat
+/setup-presign.bat
 /setup-sign.bat
 /setup-sign.bat
 /Output
 /Output
 
 

+ 1 - 1
Components/NewUxTheme.pas

@@ -1103,7 +1103,7 @@ const
   themelib = 'uxtheme.dll';
   themelib = 'uxtheme.dll';
 
 
 var
 var
-  ThemeLibrary: THandle;
+  ThemeLibrary: HMODULE;
   ReferenceCount: Integer;  // We have to keep track of several load/unload calls.
   ReferenceCount: Integer;  // We have to keep track of several load/unload calls.
 
 
 procedure FreeThemeLibrary;
 procedure FreeThemeLibrary;

+ 1 - 1
Components/RestartManager.pas

@@ -106,7 +106,7 @@ const
   restartmanagerlib = 'Rstrtmgr.dll';
   restartmanagerlib = 'Rstrtmgr.dll';
 
 
 var
 var
-  RestartManagerLibrary: THandle;
+  RestartManagerLibrary: HMODULE;
   ReferenceCount: Integer;  // We have to keep track of several load/unload calls.
   ReferenceCount: Integer;  // We have to keep track of several load/unload calls.
 
 
 procedure FreeRestartManagerLibrary;
 procedure FreeRestartManagerLibrary;

+ 2 - 0
Files/.gitignore

@@ -3,3 +3,5 @@
 *.e32
 *.e32
 *.dll
 *.dll
 *.exe
 *.exe
+/ISCmplr.dll.issig
+/ISPP.dll.issig

+ 4 - 3
ISHelp/.gitignore

@@ -1,3 +1,4 @@
-isxclasses_generated.xml
-isxfunc_generated.xml
-ispp_generated.xml
+/compilesettings.bat
+/isxclasses_generated.xml
+/isxfunc_generated.xml
+/ispp_generated.xml

+ 8 - 2
ISHelp/isetup.xml

@@ -2819,13 +2819,13 @@ Name: bosskey; KeyFile: "boss.ispublickey"
 
 
 <param name="Name" required="yes">
 <param name="Name" required="yes">
 <p>The internal name of the key.</p>
 <p>The internal name of the key.</p>
-<p>Key names are not stored in the resulting Setup file(s), so you may use personal or non-public information in your key names, like the names of developers.</p>
+<p>Key names are not stored in the resulting Setup file(s), so you may use personal or non-public information in them, like the names of developers.</p>
 <example><pre>Name: "MyKey"</pre></example>
 <example><pre>Name: "MyKey"</pre></example>
 </param>
 </param>
 
 
 <param name="Group">
 <param name="Group">
 <p>A space separated list of internal group names, specifying how to group the key.</p>
 <p>A space separated list of internal group names, specifying how to group the key.</p>
-<p>Group names are not stored in the resulting Setup file(s), so you may use personal or non-public information in your key group names, like the names of developer groups.</p>
+<p>Group names are not stored in the resulting Setup file(s), so you may use personal or non-public information in them, like the names of developer groups.</p>
 <example><pre>Group: "exesigner docsigner"</pre></example>
 <example><pre>Group: "exesigner docsigner"</pre></example>
 </param>
 </param>
 
 
@@ -2853,6 +2853,12 @@ Name: bosskey; KeyFile: "boss.ispublickey"
 <example><pre>PublicY: "e419041c3f54551e86a1c47f387005cd535dfc9d64339b30d37f9a4f7866b650"</pre></example>
 <example><pre>PublicY: "e419041c3f54551e86a1c47f387005cd535dfc9d64339b30d37f9a4f7866b650"</pre></example>
 </param>
 </param>
 
 
+<param name="RuntimeID">
+<p>Specifies the runtime ID of the key, used by <link topic="isxfunc_ISSigVerify">ISSigVerify</link>.</p>
+<p>Runtime ID's are stored in the resulting Setup file(s), so you should <i>not</i> use personal or non-public information in them.</p>
+<example><pre>RuntimeID: "def01"</pre></example>
+</param>
+
 </paramlist>
 </paramlist>
 
 
 <heading>Remarks</heading>
 <heading>Remarks</heading>

+ 5 - 16
ISHelp/isxfunc.xml

@@ -1925,26 +1925,15 @@ end;</pre>
       </function>
       </function>
     </subcategory>
     </subcategory>
     <subcategory>
     <subcategory>
-      <function>
-        <name>ISSigLoadTextFromFile</name>
-        <prototype>function ISSigLoadTextFromFile(const Filename: String): String;</prototype>
-        <description><p>Preferred, hardened function for loading specified Inno Setup Signature Tool key file text. Can also load .issig file text. An exception will be raised upon failure.</p></description>
-        <seealso><p><link topic="isxfunc_ISSigVerify">ISSigVerify</link></p></seealso>
-      </function>
       <function>
       <function>
         <name>ISSigVerify</name>
         <name>ISSigVerify</name>
-        <prototype>function ISSigVerify(const AllowedKeysTexts: TArrayOfString; const Filename: String; const KeepOpen: Boolean): TFileStream;</prototype>
-        <description><p>Verifies the signature of specified file using the specified key texts. An exception will be raised upon failure.</p>
-<p>Returns a handle to the still open file if True is specified in the KeepOpen parameter, <tt>nil</tt> otherwise. It is recommended that you always specify True if you plan to use the file for anything after verification. Otherwise, you risk creating a Time-Of-Check to Time-Of-Use (TOCTOU) problem.</p>
-<p>Key text from files should be loaded using <link topic="isxfunc_ISSigLoadTextFromFile">ISSigLoadTextFromFile</link>.</p></description>
+        <prototype>function ISSigVerify(const AllowedKeysRuntimeIDs: TArrayOfString; const Filename: String; const KeepOpen: Boolean): TFileStream;</prototype>
+        <description><p>Verifies the signature of the specified file using the specified allowed keys, looked up using [ISSigKeys] section parameter <tt>RuntimeID</tt>. If no keys are specified then all keys are allowed. An exception will be raised upon failure.</p>
+<p>Returns a handle to the still open file if True is specified in the KeepOpen parameter, <tt>nil</tt> otherwise. It is recommended that you always specify True if you plan to use the file for anything after verification. Otherwise, you risk creating a Time-Of-Check to Time-Of-Use (TOCTOU) problem.</p></description>
         <example><pre>var
         <example><pre>var
-  AllowedKeyText: String;
-  AllowedKeysText: TArrayOfString;
+  F: TFileStream;
 begin
 begin
-  AllowedKeyText := ISSigLoadTextFromFile(KeyFilename);
-  SetLength(AllowedKeysText, 1);
-  AllowedKeysText[0] := AllowedKeyText;
-  F := ISSigVerify(AllowedKeysText, Filename, True);
+  F := ISSigVerify([], Filename, True);
   try
   try
     // Use file
     // Use file
   finally
   finally

+ 1 - 1
Projects/Src/Compiler.Messages.pas

@@ -252,7 +252,7 @@ const
   SCompilerTasksInvalidLevel = 'Task cannot be more than one level below the preceding task';
   SCompilerTasksInvalidLevel = 'Task cannot be more than one level below the preceding task';
   SCompilerLanguagesOrISSigKeysBadName = 'Parameter "%s" includes invalid characters.' + SNewLine2 + 'It may only include alphanumeric characters and/or underscores, and may not start with a number. Names ''not'', ''and'' and ''or'' are reserved';
   SCompilerLanguagesOrISSigKeysBadName = 'Parameter "%s" includes invalid characters.' + SNewLine2 + 'It may only include alphanumeric characters and/or underscores, and may not start with a number. Names ''not'', ''and'' and ''or'' are reserved';
   SCompilerLanguagesOrISSigKeysBadGroupName = 'Parameter "%s" includes a name with invalid characters.' + SNewLine2 + 'Names may only include alphanumeric characters and/or underscores, and may not start with a number. Names ''not'', ''and'' and ''or'' are reserved';
   SCompilerLanguagesOrISSigKeysBadGroupName = 'Parameter "%s" includes a name with invalid characters.' + SNewLine2 + 'Names may only include alphanumeric characters and/or underscores, and may not start with a number. Names ''not'', ''and'' and ''or'' are reserved';
-  SCompilerISSigKeysNameExists = 'Name "%s" is already in use"';
+  SCompilerISSigKeysNameOrRuntimeIDExists = '%s "%s" is already in use"';
   SCompilerISSigKeysKeyNotSpecified = 'Required parameter(s) "KeyFile" or "PublicX"/"PublicY" not specified';
   SCompilerISSigKeysKeyNotSpecified = 'Required parameter(s) "KeyFile" or "PublicX"/"PublicY" not specified';
   SCompilerISSigKeysBadKeyID = 'Value of parameter "KeyID" is not valid for given "KeyFile" or "PublicX"/"PublicY" values.';
   SCompilerISSigKeysBadKeyID = 'Value of parameter "KeyID" is not valid for given "KeyFile" or "PublicX"/"PublicY" values.';
   SCompilerISSigKeysBadKeyFile = 'Key file is malformed';
   SCompilerISSigKeysBadKeyFile = 'Key file is malformed';

+ 20 - 4
Projects/Src/Compiler.SetupCompiler.pas

@@ -4501,8 +4501,18 @@ procedure TSetupCompiler.EnumISSigKeysProc(const Line: PChar; const Ext: Integer
     Result := False;
     Result := False;
   end;
   end;
 
 
+  function ISSigKeysRuntimeIDExists(const RuntimeID: String): Boolean;
+  begin
+    for var I := 0 to ISSigKeyEntries.Count-1 do begin
+      var ISSigKeyEntry := PSetupISSigKeyEntry(ISSigKeyEntries[I]);
+      if SameText(ISSigKeyEntry.RuntimeID, RuntimeID) then
+        Exit(True)
+    end;
+    Result := False;
+  end;
+
 type
 type
-  TParam = (paName, paGroup, paKeyFile, paKeyID, paPublicX, paPublicY);
+  TParam = (paName, paGroup, paKeyFile, paKeyID, paPublicX, paPublicY, paRuntimeID);
 const
 const
   ParamISSigKeysName = 'Name';
   ParamISSigKeysName = 'Name';
   ParamISSigKeysGroup = 'Group';
   ParamISSigKeysGroup = 'Group';
@@ -4510,13 +4520,15 @@ const
   ParamISSigKeysKeyID = 'KeyID';
   ParamISSigKeysKeyID = 'KeyID';
   ParamISSigKeysPublicX = 'PublicX';
   ParamISSigKeysPublicX = 'PublicX';
   ParamISSigKeysPublicY = 'PublicY';
   ParamISSigKeysPublicY = 'PublicY';
+  ParamISSigKeysRuntimeID = 'RuntimeID';
   ParamInfo: array[TParam] of TParamInfo = (
   ParamInfo: array[TParam] of TParamInfo = (
     (Name: ParamISSigKeysName; Flags: [piRequired, piNoEmpty]),
     (Name: ParamISSigKeysName; Flags: [piRequired, piNoEmpty]),
     (Name: ParamISSigKeysGroup; Flags: []),
     (Name: ParamISSigKeysGroup; Flags: []),
     (Name: ParamISSigKeysKeyFile; Flags: [piNoEmpty]),
     (Name: ParamISSigKeysKeyFile; Flags: [piNoEmpty]),
     (Name: ParamISSigKeysKeyID; Flags: [piNoEmpty]),
     (Name: ParamISSigKeysKeyID; Flags: [piNoEmpty]),
     (Name: ParamISSigKeysPublicX; Flags: [piNoEmpty]),
     (Name: ParamISSigKeysPublicX; Flags: [piNoEmpty]),
-    (Name: ParamISSigKeysPublicY; Flags: [piNoEmpty]));
+    (Name: ParamISSigKeysPublicY; Flags: [piNoEmpty]),
+    (Name: ParamISSigKeysRuntimeID; Flags: [piNoEmpty]));
 var
 var
   Values: array[TParam] of TParamValue;
   Values: array[TParam] of TParamValue;
   NewISSigKeyEntry: PSetupISSigKeyEntry;
   NewISSigKeyEntry: PSetupISSigKeyEntry;
@@ -4534,7 +4546,7 @@ begin
       if not IsValidIdentString(Name, False, False) then
       if not IsValidIdentString(Name, False, False) then
         AbortCompileFmt(SCompilerLanguagesOrISSigKeysBadName, [ParamISSigKeysName])
         AbortCompileFmt(SCompilerLanguagesOrISSigKeysBadName, [ParamISSigKeysName])
       else if ISSigKeysNameExists(Name, True) then
       else if ISSigKeysNameExists(Name, True) then
-        AbortCompileFmt(SCompilerISSigKeysNameExists, [Name]);
+        AbortCompileFmt(SCompilerISSigKeysNameOrRuntimeIDExists, [ParamISSigKeysName, Name]);
 
 
       { Group }
       { Group }
       var S := Values[paGroup].Data;
       var S := Values[paGroup].Data;
@@ -4545,7 +4557,7 @@ begin
         if not IsValidIdentString(GroupName, False, False) then
         if not IsValidIdentString(GroupName, False, False) then
           AbortCompileFmt(SCompilerLanguagesOrISSigKeysBadGroupName, [ParamISSigKeysGroup])
           AbortCompileFmt(SCompilerLanguagesOrISSigKeysBadGroupName, [ParamISSigKeysGroup])
         else if SameText(Name, GroupName) or ISSigKeysNameExists(GroupName, False) then
         else if SameText(Name, GroupName) or ISSigKeysNameExists(GroupName, False) then
-          AbortCompileFmt(SCompilerISSigKeysNameExists, [GroupName]);
+          AbortCompileFmt(SCompilerISSigKeysNameOrRuntimeIDExists, [ParamISSigKeysName, GroupName]);
         if not HasGroupName(GroupName) then begin
         if not HasGroupName(GroupName) then begin
           const N = Length(GroupNames);
           const N = Length(GroupNames);
           SetLength(GroupNames, N+1);
           SetLength(GroupNames, N+1);
@@ -4604,6 +4616,10 @@ begin
         if not ISSigIsValidKeyIDForPublicXY(KeyID, PublicX, PublicY) then
         if not ISSigIsValidKeyIDForPublicXY(KeyID, PublicX, PublicY) then
           AbortCompile(SCompilerISSigKeysBadKeyID);
           AbortCompile(SCompilerISSigKeysBadKeyID);
       end;
       end;
+
+      RuntimeID := Values[paRuntimeID].Data;
+      if ISSigKeysRuntimeIDExists(RuntimeID) then
+        AbortCompileFmt(SCompilerISSigKeysNameOrRuntimeIDExists, [ParamISSigKeysRuntimeID, RuntimeID]);
     end;
     end;
   except
   except
     SEFreeRec(NewISSigKeyEntry, SetupISSigKeyEntryStrings, SetupISSigKeyEntryAnsiStrings);
     SEFreeRec(NewISSigKeyEntry, SetupISSigKeyEntryStrings, SetupISSigKeyEntryAnsiStrings);

+ 1 - 1
Projects/Src/IDE.ScintStylerInnoSetup.pas

@@ -235,7 +235,7 @@ const
   ];
   ];
 
 
   ISSigKeysSectionParameters: array of TScintRawString = [
   ISSigKeysSectionParameters: array of TScintRawString = [
-    'Name', 'Group', 'KeyFile', 'KeyID', 'PublicX', 'PublicY'
+    'Name', 'Group', 'KeyFile', 'KeyID', 'PublicX', 'PublicY', 'RuntimeID'
   ];
   ];
 
 
   FilesSectionParameters: array of TScintRawString = [
   FilesSectionParameters: array of TScintRawString = [

+ 1 - 13
Projects/Src/Setup.Install.pas

@@ -31,7 +31,7 @@ uses
   Windows, SysUtils, Messages, Classes, Forms, ShlObj, Shared.Struct, Setup.UninstallLog, Shared.SetupTypes,
   Windows, SysUtils, Messages, Classes, Forms, ShlObj, Shared.Struct, Setup.UninstallLog, Shared.SetupTypes,
   SetupLdrAndSetup.InstFunc, Setup.InstFunc, Setup.InstFunc.Ole, Setup.SecurityFunc, SetupLdrAndSetup.Messages,
   SetupLdrAndSetup.InstFunc, Setup.InstFunc, Setup.InstFunc.Ole, Setup.SecurityFunc, SetupLdrAndSetup.Messages,
   Setup.MainFunc, Setup.LoggingFunc, Setup.FileExtractor, Shared.FileClass,
   Setup.MainFunc, Setup.LoggingFunc, Setup.FileExtractor, Shared.FileClass,
-  Compression.Base, SHA256, PathFunc, ECDSA, ISSigFunc, Shared.CommonFunc.Vcl,
+  Compression.Base, SHA256, PathFunc, ISSigFunc, Shared.CommonFunc.Vcl,
   Shared.CommonFunc, SetupLdrAndSetup.RedirFunc, Shared.Int64Em, Shared.SetupMessageIDs,
   Shared.CommonFunc, SetupLdrAndSetup.RedirFunc, Shared.Int64Em, Shared.SetupMessageIDs,
   Setup.WizardForm, Shared.DebugStruct, Setup.DebugClient, Shared.VerInfoFunc, Setup.ScriptRunner, Setup.RegDLL, Setup.Helper,
   Setup.WizardForm, Shared.DebugStruct, Setup.DebugClient, Shared.VerInfoFunc, Setup.ScriptRunner, Setup.RegDLL, Setup.Helper,
   Shared.ResUpdateFunc, Setup.DotNetFunc, TaskbarProgressFunc, NewProgressBar, RestartManager,
   Shared.ResUpdateFunc, Setup.DotNetFunc, TaskbarProgressFunc, NewProgressBar, RestartManager,
@@ -397,7 +397,6 @@ var
   UninstallDataCreated, UninstallMsgCreated, AppendUninstallData: Boolean;
   UninstallDataCreated, UninstallMsgCreated, AppendUninstallData: Boolean;
   RegisterFilesList: TList;
   RegisterFilesList: TList;
   ExpandedAppId: String;
   ExpandedAppId: String;
-  ISSigAvailableKeys: TArrayOfECDSAKey;
 
 
   function GetLocalTimeAsStr: String;
   function GetLocalTimeAsStr: String;
   var
   var
@@ -3134,7 +3133,6 @@ begin
   AppendUninstallData := False;
   AppendUninstallData := False;
   UninstLogCleared := False;
   UninstLogCleared := False;
   RegisterFilesList := nil;
   RegisterFilesList := nil;
-  SetLength(ISSigAvailableKeys, 0);
   UninstLog := TSetupUninstallLog.Create;
   UninstLog := TSetupUninstallLog.Create;
   try
   try
     try
     try
@@ -3172,14 +3170,6 @@ begin
 
 
       RegisterFilesList := TList.Create;
       RegisterFilesList := TList.Create;
 
 
-      SetLength(ISSigAvailableKeys, Entries[seISSigKey].Count);
-      for var N := 0 to Entries[seISSigKey].Count-1 do begin
-        var ISSigKeyEntry := PSetupISSigKeyEntry(Entries[seISSigKey][N]);
-        ISSigAvailableKeys[N] := TECDSAKey.Create;
-        if ISSigImportPublicKey(ISSigAvailableKeys[N], '', ISSigKeyEntry.PublicX, ISSigKeyEntry.PublicY) <> ikrSuccess then
-          InternalError('ISSigImportPublicKey failed')
-      end;
-
       { Process Component entries, if any }
       { Process Component entries, if any }
       ProcessComponentEntries;
       ProcessComponentEntries;
       ProcessEvents;
       ProcessEvents;
@@ -3340,8 +3330,6 @@ begin
       Exit;
       Exit;
     end;
     end;
   finally
   finally
-    for I := 0 to Length(ISSigAvailableKeys)-1 do
-      ISSigAvailableKeys[I].Free;
     if Assigned(RegisterFilesList) then begin
     if Assigned(RegisterFilesList) then begin
       for I := RegisterFilesList.Count-1 downto 0 do
       for I := RegisterFilesList.Count-1 downto 0 do
         Dispose(PRegisterFilesListRec(RegisterFilesList[I]));
         Dispose(PRegisterFilesListRec(RegisterFilesList[I]));

+ 14 - 1
Projects/Src/Setup.MainFunc.pas

@@ -111,6 +111,7 @@ var
   WizardImages: TList;
   WizardImages: TList;
   WizardSmallImages: TList;
   WizardSmallImages: TList;
   CloseApplicationsFilterList, CloseApplicationsFilterExcludesList: TStringList;
   CloseApplicationsFilterList, CloseApplicationsFilterExcludesList: TStringList;
+  ISSigAvailableKeys: TArrayOfECDSAKey;
 
 
   { User options }
   { User options }
   ActiveLanguage: Integer = -1;
   ActiveLanguage: Integer = -1;
@@ -236,7 +237,7 @@ function IsWindows11: Boolean;
 implementation
 implementation
 
 
 uses
 uses
-  ShellAPI, ShlObj, StrUtils, ActiveX, RegStr, ChaCha20,
+  ShellAPI, ShlObj, StrUtils, ActiveX, RegStr, ChaCha20, ECDSA, ISSigFunc,
   SetupLdrAndSetup.Messages, Shared.SetupMessageIDs, Setup.Install, SetupLdrAndSetup.InstFunc,
   SetupLdrAndSetup.Messages, Shared.SetupMessageIDs, Setup.Install, SetupLdrAndSetup.InstFunc,
   Setup.InstFunc, SetupLdrAndSetup.RedirFunc, PathFunc,
   Setup.InstFunc, SetupLdrAndSetup.RedirFunc, PathFunc,
   Compression.Base, Compression.Zlib, Compression.bzlib, Compression.LZMADecompressor,
   Compression.Base, Compression.Zlib, Compression.bzlib, Compression.LZMADecompressor,
@@ -3228,6 +3229,15 @@ begin
   { Set install mode }
   { Set install mode }
   SetupInstallMode;
   SetupInstallMode;
 
 
+  { Init ISSigAvailableKeys }
+  SetLength(ISSigAvailableKeys, Entries[seISSigKey].Count);
+  for I := 0 to Entries[seISSigKey].Count-1 do begin
+    var ISSigKeyEntry := PSetupISSigKeyEntry(Entries[seISSigKey][I]);
+    ISSigAvailableKeys[I] := TECDSAKey.Create;
+    if ISSigImportPublicKey(ISSigAvailableKeys[I], '', ISSigKeyEntry.PublicX, ISSigKeyEntry.PublicY) <> ikrSuccess then
+      InternalError('ISSigImportPublicKey failed')
+  end;
+
   { Load and initialize code }
   { Load and initialize code }
   if SetupHeader.CompiledCodeText <> '' then begin
   if SetupHeader.CompiledCodeText <> '' then begin
     CodeRunner := TScriptRunner.Create();
     CodeRunner := TScriptRunner.Create();
@@ -3473,6 +3483,9 @@ begin
       DeleteDirsAfterInstallList[I]);
       DeleteDirsAfterInstallList[I]);
   DeleteDirsAfterInstallList.Clear;
   DeleteDirsAfterInstallList.Clear;
 
 
+  for I := 0 to Length(ISSigAvailableKeys)-1 do
+    ISSigAvailableKeys[I].Free;
+
   FreeFileExtractor;
   FreeFileExtractor;
 
 
   { End RestartManager session }
   { End RestartManager session }

+ 45 - 47
Projects/Src/Setup.ScriptFunc.pas

@@ -1816,61 +1816,59 @@ var
         Parts := Stack.GetString(PStart-1).Split(Separators, TStringSplitOptions(Stack.GetInt(PStart-3)));
         Parts := Stack.GetString(PStart-1).Split(Separators, TStringSplitOptions(Stack.GetInt(PStart-3)));
       Stack.SetArray(PStart, Parts);
       Stack.SetArray(PStart, Parts);
     end);
     end);
-    RegisterScriptFunc('ISSigLoadTextFromFile', procedure(const Caller: TPSExec; const OrgName: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
-    begin
-      Stack.SetString(PStart, ISSigLoadTextFromFile(Stack.GetString(PStart-1)));
-    end);
     RegisterScriptFunc('ISSigVerify', procedure(const Caller: TPSExec; const OrgName: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     RegisterScriptFunc('ISSigVerify', procedure(const Caller: TPSExec; const OrgName: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
     begin
-      const AllowedKeysTexts = Stack.GetStringArray(PStart-1);
+      const AllowedKeysRuntimeIDs = Stack.GetStringArray(PStart-1);
       const Filename = Stack.GetString(PStart-2);
       const Filename = Stack.GetString(PStart-2);
       const KeepOpen = Stack.GetBool(PStart-3);
       const KeepOpen = Stack.GetBool(PStart-3);
 
 
-      var ExpectedFileSize: Int64;
-      var ExpectedFileHash: TSHA256Digest;
-
-      var AllowedKeys: TArrayOfECDSAKey;
-      const NAllowedKeys = Length(AllowedKeysTexts);
-      SetLength(AllowedKeys, NAllowedKeys);
-      try
-        { Import keys }
-        for var I := 0 to NAllowedKeys-1 do begin
-          AllowedKeys[I] := TECDSAKey.Create;
-          const ImportResult = ISSigImportKeyText(AllowedKeys[I], AllowedKeysTexts[I], False);
-          if ImportResult = ikrMalformed then
-            InternalError('Key text is malformed')
-          else if ImportResult <> ikrSuccess then
-            InternalError('Unknown import key result');
+      { Import keys }
+      var ISSigAllowedKeys: AnsiString;
+      for var I := 0 to Length(AllowedKeysRuntimeIDs)-1 do begin
+        const RuntimeID = AllowedKeysRuntimeIDs[I];
+        if RuntimeID = '' then
+          InternalError('RuntimeID cannot be empty');
+        var Found := False;
+        for var KeyIndex := 0 to Entries[seISSigKey].Count-1 do begin
+          var ISSigKeyEntry := PSetupISSigKeyEntry(Entries[seISSigKey][KeyIndex]);
+          if SameText(ISSigKeyEntry.RuntimeID, RuntimeID) then begin
+            SetISSigAllowedKey(ISSigAllowedKeys, KeyIndex);
+            Found := True;
+            Break;
+          end;
         end;
         end;
-
-        { Verify signature }
-        if not ISSigVerifySignature(Filename, AllowedKeys, ExpectedFileSize, ExpectedFileHash,
-          procedure(const Filename: String)
-          begin
-            raise Exception.Create('File does not exist');
-          end,
-          procedure(const Filename, SigFilename: String)
-          begin
-            raise Exception.Create('Signature file does not exist');
-          end,
-          procedure(const SigFilename: String; const VerifyResult: TISSigVerifySignatureResult)
-          begin
-            case VerifyResult of
-              vsrMalformed, vsrBadSignature:
-                raise Exception.Create('Signature file is not valid');
-              vsrKeyNotFound:
-                raise Exception.Create('Incorrect key ID');
-            else
-              InternalError('Unknown verify result');
-            end;
-          end
-        ) then
-          InternalError('Unexpected ISSigVerifySignature result');
-      finally
-        for var I := 0 to NAllowedKeys-1 do
-          AllowedKeys[I].Free;
+        if not Found then
+          InternalError(Format('Unknown RuntimeID ''%s''', [RuntimeID]));
       end;
       end;
 
 
+      { Verify signature }
+      var ExpectedFileSize: Int64;
+      var ExpectedFileHash: TSHA256Digest;
+      if not ISSigVerifySignature(Filename,
+        GetISSigAllowedKeys(ISSigAvailableKeys, ISSigAllowedKeys),
+        ExpectedFileSize, ExpectedFileHash,
+        procedure(const Filename: String)
+        begin
+          raise Exception.Create('File does not exist');
+        end,
+        procedure(const Filename, SigFilename: String)
+        begin
+          raise Exception.Create('Signature file does not exist');
+        end,
+        procedure(const SigFilename: String; const VerifyResult: TISSigVerifySignatureResult)
+        begin
+          case VerifyResult of
+            vsrMalformed, vsrBadSignature:
+              raise Exception.Create('Signature file is not valid');
+            vsrKeyNotFound:
+              raise Exception.Create('Incorrect key ID');
+          else
+            InternalError('Unknown verify result');
+          end;
+        end
+      ) then
+        InternalError('Unexpected ISSigVerifySignature result');
+
       { Verify file, keeping open afterwards if requested }
       { Verify file, keeping open afterwards if requested }
       var F := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
       var F := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
       try
       try

+ 1 - 2
Projects/Src/Shared.ScriptFunc.pas

@@ -546,8 +546,7 @@ initialization
     'function StringJoin(const Separator: String; const Values: TArrayOfString): String;',
     'function StringJoin(const Separator: String; const Values: TArrayOfString): String;',
     'function StringSplit(const S: String; const Separators: TArrayOfString; const Typ: TSplitType): TArrayOfString;',
     'function StringSplit(const S: String; const Separators: TArrayOfString; const Typ: TSplitType): TArrayOfString;',
     'function StringSplitEx(const S: String; const Separators: TArrayOfString; const Quote: Char; const Typ: TSplitType): TArrayOfString;',
     'function StringSplitEx(const S: String; const Separators: TArrayOfString; const Quote: Char; const Typ: TSplitType): TArrayOfString;',
-    'function ISSigLoadTextFromFile(const Filename: String): String;',
-    'function ISSigVerify(const AllowedKeysTexts: TArrayOfString; const Filename: String; const KeepOpen: Boolean): TFileStream;'
+    'function ISSigVerify(const AllowedKeysRuntimeIDs: TArrayOfString; const Filename: String; const KeepOpen: Boolean): TFileStream;'
   ];
   ];
 
 
   {$IFDEF COMPIL32PROJ}
   {$IFDEF COMPIL32PROJ}

+ 3 - 3
Projects/Src/Shared.SetupTypes.pas

@@ -312,11 +312,10 @@ begin
   Move(KeyBytes[0], Key[0], KeyLength);
   Move(KeyBytes[0], Key[0], KeyLength);
 end;
 end;
 
 
-{ Actually only used by ISCmplr and not by Setup - kept here anyway because IsISSigAllowedKey is}
 procedure SetISSigAllowedKey(var ISSigAllowedKeys: AnsiString; const KeyIndex: Integer);
 procedure SetISSigAllowedKey(var ISSigAllowedKeys: AnsiString; const KeyIndex: Integer);
+{ ISSigAllowedKeys should start out empty. If you then only use this function
+  to update it, regular string comparison can be used for comparisons. }
 begin
 begin
-  { ISSigAllowedKeys should start out empty. If you then only use this function
-    to update it, regular string comparison can be used for comparisons. }
   const ByteIndex = KeyIndex div 8;
   const ByteIndex = KeyIndex div 8;
   while ByteIndex >= Length(ISSigAllowedKeys) do
   while ByteIndex >= Length(ISSigAllowedKeys) do
     ISSigAllowedKeys := ISSigAllowedKeys + #0;
     ISSigAllowedKeys := ISSigAllowedKeys + #0;
@@ -335,6 +334,7 @@ end;
 
 
 function GetISSigAllowedKeys([Ref] const ISSigAvailableKeys: TArrayOfECDSAKey;
 function GetISSigAllowedKeys([Ref] const ISSigAvailableKeys: TArrayOfECDSAKey;
   const ISSigAllowedKeys: AnsiString): TArrayOfECDSAKey;
   const ISSigAllowedKeys: AnsiString): TArrayOfECDSAKey;
+{ Returns all keys if ISSigAllowedKeys is empty! }
 begin
 begin
   if ISSigAllowedKeys <> '' then begin
   if ISSigAllowedKeys <> '' then begin
     const NAvailable = Length(ISSigAvailableKeys);
     const NAvailable = Length(ISSigAvailableKeys);

+ 2 - 2
Projects/Src/Shared.Struct.pas

@@ -218,12 +218,12 @@ type
       doUninsAlwaysUninstall, doSetNTFSCompression, doUnsetNTFSCompression);
       doUninsAlwaysUninstall, doSetNTFSCompression, doUnsetNTFSCompression);
   end;
   end;
 const
 const
-  SetupISSigKeyEntryStrings = 2;
+  SetupISSigKeyEntryStrings = 3;
   SetupISSigKeyEntryAnsiStrings = 0;
   SetupISSigKeyEntryAnsiStrings = 0;
 type
 type
   PSetupISSigKeyEntry = ^TSetupISSigKeyEntry;
   PSetupISSigKeyEntry = ^TSetupISSigKeyEntry;
   TSetupISSigKeyEntry = packed record
   TSetupISSigKeyEntry = packed record
-    PublicX, PublicY: String;
+    PublicX, PublicY, RuntimeID: String;
   end;
   end;
 const
 const
   SetupFileEntryStrings = 11;
   SetupFileEntryStrings = 11;

+ 2 - 0
issig.bat

@@ -23,6 +23,8 @@ echo compilesettings.bat is missing or incomplete. It needs to contain
 echo the following line, adjusted for your system:
 echo the following line, adjusted for your system:
 echo.
 echo.
 echo   set ISSIGTOOL_KEY_FILE=x:\path\MyKey.isprivatekey
 echo   set ISSIGTOOL_KEY_FILE=x:\path\MyKey.isprivatekey
+echo.
+echo Keep the path outside of your source tree!
 goto failed2
 goto failed2
 
 
 :compilesettingsfound
 :compilesettingsfound

+ 1 - 1
whatsnew.htm

@@ -48,7 +48,7 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
   <li>New <tt>[ISSigKeys]</tt> section:
   <li>New <tt>[ISSigKeys]</tt> section:
   <ul>
   <ul>
     <li>Added a new optional <tt>[ISSigKeys]</tt> section for defining keys used by the compiler and Setup to verify file signatures.</li>
     <li>Added a new optional <tt>[ISSigKeys]</tt> section for defining keys used by the compiler and Setup to verify file signatures.</li>
-    <li>Supports parameters <tt>Name</tt> (required) and <tt>Group</tt> to identify keys, parameters <tt>KeyFile</tt>, <tt>PublicX</tt>, and <tt>PublicY</tt> to specify the key values, and parameter <tt>KeyID</tt> to double-check the key values.</li>
+    <li>Supports parameters <tt>Name</tt> (required) and <tt>Group</tt> to identify keys, parameters <tt>KeyFile</tt>, <tt>PublicX</tt>, and <tt>PublicY</tt> to specify the key values, parameter <tt>KeyID</tt> to double-check the key values, and parameter <tt>RuntimeID</tt> for runtime identification of the key.</li>
     <li>Key files are human-readable and can be created using Inno Setup Signature Tool (see below).</li>
     <li>Key files are human-readable and can be created using Inno Setup Signature Tool (see below).</li>
     <li>Example section:
     <li>Example section:
       <pre>[ISSigKeys]
       <pre>[ISSigKeys]