Browse Source

Use ISSigFunc to check trust. Works while debugging from Delphi as well. Defining TRUSTALL would only be needed while debugging isscint.dll from VS for example.

AllowedPublicKeyText is formatted as a Delphi 12 multiline string literal since I plan to make ISSigTool embed it automatically from issig.bat to avoid complicating the build for others.
Martijn Laan 3 months ago
parent
commit
ec81524172

+ 46 - 27
Components/TrustFunc.pas

@@ -7,9 +7,7 @@ unit TrustFunc;
   For conditions of distribution and use, see LICENSE.TXT.
 }
 
-{$IFDEF DEBUG}
-{$DEFINE TRUSTALL}
-{$ENDIF}
+{.$DEFINE TRUSTALL}
 
 interface
 
@@ -18,35 +16,56 @@ function TrustedFileExists(const FileName: String): Boolean;
 implementation
 
 uses
-  Winapi.Windows {$IFDEF TRUSTALL}, System.SysUtils {$ENDIF};
+  Winapi.Windows, System.SysUtils {$IFNDEF TRUSTALL}, System.Classes, ECDSA, SHA256, ISSigFunc {$ENDIF};
 
 function TrustedFileExists(const FileName: String): Boolean;
 begin
-{$IFNDEF TRUSTALL}
-  var FileInfo: TWinTrustFileInfo;
-  ZeroMemory(@FileInfo, SizeOf(FileInfo));
-  FileInfo.cbStruct := SizeOf(FileInfo);
-  FileInfo.pcwszFilePath := PChar(FileName);
-
-  var WinTrustData: TWinTrustData;
-  ZeroMemory(@WinTrustData, SizeOf(WinTrustData));
-  WinTrustData.cbStruct := SizeOf(WinTrustData);
-  WinTrustData.dwUIChoice := WTD_UI_NONE;
-  WinTrustData.fdwRevocationChecks := WTD_REVOKE_NONE;
-  WinTrustData.dwUnionChoice := WTD_CHOICE_FILE;
-  WinTrustData.pFile := @FileInfo;
-  WinTrustData.dwStateAction := WTD_STATEACTION_VERIFY;
-  WinTrustData.dwProvFlags := WTD_REVOCATION_CHECK_NONE;
-
-  var PolicyGUID := WINTRUST_ACTION_GENERIC_VERIFY_V2;
-
-  Result := WinVerifyTrust(0, PolicyGUID, @WinTrustData) = 0;
-
-  WinTrustData.dwStateAction := WTD_STATEACTION_CLOSE;
-  WinVerifyTrust(0, PolicyGUID, @WinTrustData);
-{$ELSE}
   var Attr := GetFileAttributes(PChar(FileName));
   Result := (Attr <> INVALID_FILE_ATTRIBUTES) and (Attr and faDirectory = 0);
+{$IFNDEF TRUSTALL}
+  if Result then begin
+    try
+      const
+        AllowedPublicKeyText = '''
+format issig-public-key
+key-id c2587f3885b12463bafdadb799f23435f26c03944c1afc1716aabc6a43f2426f
+public-x f9a30c72189077370a8846015ac3ec1e9a1cf425d2996d34dc25bd4f4923dd1b
+public-y f754897b7819da5bbbc5ac568311eee922fbea492578748e07f453dc1289c532
+
+''';
+      const Key = TECDSAKey.Create;
+      try
+        if ISSigImportKeyText(Key, AllowedPublicKeyText, False) <> ikrSuccess then
+          raise Exception.Create('ISSigImportKeyText failed');
+
+        const SigFileName = FileName + '.issig';
+        const SigText = ISSigLoadTextFromFile(SigFileName);
+
+        var ExpectedFileSize: Int64;
+        var ExpectedFileHash: TSHA256Digest;
+        if ISSigVerifySignatureText([Key], SigText, ExpectedFileSize,
+           ExpectedFileHash) <> vsrSuccess then
+          raise Exception.CreateFmt('Signature file "%s" is not valid',
+            [SigFileName]);
+
+        const F = TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+        try
+          if F.Size <> ExpectedFileSize then
+            raise Exception.CreateFmt('File "%s" is not trusted (incorrect size).',
+              [FileName]);
+          if not SHA256DigestsEqual(ISSigCalcStreamHash(F), ExpectedFileHash) then
+            raise Exception.CreateFmt('File "%s" is not trusted (incorrect hash).',
+              [FileName]);
+        finally
+          F.Free;
+        end;
+      finally
+        Key.Free;
+      end;
+    except
+      Result := False;
+    end;
+  end;
 {$ENDIF}
 end;
 

+ 4 - 1
Projects/Compil32.dpr

@@ -69,7 +69,10 @@ uses
   SHA256 in '..\Components\SHA256.pas',
   Shared.DotNetVersion in 'Src\Shared.DotNetVersion.pas',
   isxclasses_wordlists_generated in '..\ISHelp\isxclasses_wordlists_generated.pas',
-  IDE.ImagesModule in 'Src\IDE.ImagesModule.pas' {ImagesModule: TDataModule};
+  IDE.ImagesModule in 'Src\IDE.ImagesModule.pas' {ImagesModule: TDataModule},
+  ECDSA in '..\Components\ECDSA.pas',
+  ISSigFunc in '..\Components\ISSigFunc.pas',
+  StringScanner in '..\Components\StringScanner.pas';
 
 {$SETPEOSVERSION 6.1}
 {$SETPESUBSYSVERSION 6.1}

+ 3 - 0
Projects/Compil32.dproj

@@ -155,6 +155,9 @@
             <FormType>dfm</FormType>
             <DesignClass>TDataModule</DesignClass>
         </DCCReference>
+        <DCCReference Include="..\Components\ECDSA.pas"/>
+        <DCCReference Include="..\Components\ISSigFunc.pas"/>
+        <DCCReference Include="..\Components\StringScanner.pas"/>
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
         </BuildConfiguration>

+ 5 - 1
Projects/ISCC.dpr

@@ -30,7 +30,11 @@ uses
   Shared.FileClass in 'Src\Shared.FileClass.pas',
   Shared.ConfigIniFile in 'Src\Shared.ConfigIniFile.pas',
   Shared.SignToolsFunc in 'Src\Shared.SignToolsFunc.pas',
-  Shared.Int64Em in 'Src\Shared.Int64Em.pas';
+  Shared.Int64Em in 'Src\Shared.Int64Em.pas',
+  SHA256 in '..\Components\SHA256.pas',
+  ECDSA in '..\Components\ECDSA.pas',
+  ISSigFunc in '..\Components\ISSigFunc.pas',
+  StringScanner in '..\Components\StringScanner.pas';
 
 {$SETPEOSVERSION 6.1}
 {$SETPESUBSYSVERSION 6.1}

+ 4 - 0
Projects/ISCC.dproj

@@ -85,6 +85,10 @@
         <DCCReference Include="Src\Shared.ConfigIniFile.pas"/>
         <DCCReference Include="Src\Shared.SignToolsFunc.pas"/>
         <DCCReference Include="Src\Shared.Int64Em.pas"/>
+        <DCCReference Include="..\Components\SHA256.pas"/>
+        <DCCReference Include="..\Components\ECDSA.pas"/>
+        <DCCReference Include="..\Components\ISSigFunc.pas"/>
+        <DCCReference Include="..\Components\StringScanner.pas"/>
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
         </BuildConfiguration>

+ 4 - 1
Projects/ISCmplr.dpr

@@ -49,7 +49,10 @@ uses
   Shared.SetupSteps in 'Src\Shared.SetupSteps.pas',
   SimpleExpression in '..\Components\SimpleExpression.pas',
   Shared.DotNetVersion in 'Src\Shared.DotNetVersion.pas',
-  PBKDF2 in '..\Components\PBKDF2.pas';
+  PBKDF2 in '..\Components\PBKDF2.pas',
+  ECDSA in '..\Components\ECDSA.pas',
+  ISSigFunc in '..\Components\ISSigFunc.pas',
+  StringScanner in '..\Components\StringScanner.pas';
 
 {$IMAGEBASE $00800000}
 {$SETPEOSVERSION 6.1}

+ 3 - 0
Projects/ISCmplr.dproj

@@ -119,6 +119,9 @@ $(PostBuildEvent)]]></PostBuildEvent>
         <DCCReference Include="..\Components\SimpleExpression.pas"/>
         <DCCReference Include="Src\Shared.DotNetVersion.pas"/>
         <DCCReference Include="..\Components\PBKDF2.pas"/>
+        <DCCReference Include="..\Components\ECDSA.pas"/>
+        <DCCReference Include="..\Components\ISSigFunc.pas"/>
+        <DCCReference Include="..\Components\StringScanner.pas"/>
         <BuildConfiguration Include="Base">
             <Key>Base</Key>
         </BuildConfiguration>