Jelajahi Sumber

ECDSA: Load bcrypt.dll dynamically.

Just to ensure it's loaded from System32, and never from the application directory.

Jordan Russell 3 bulan lalu
induk
melakukan
6d3269836c
1 mengubah file dengan 72 tambahan dan 31 penghapusan
  1. 72 31
      Components/ECDSA.pas

+ 72 - 31
Components/ECDSA.pas

@@ -76,46 +76,47 @@ const
 
   STATUS_INVALID_SIGNATURE = NTSTATUS($C000A000);
 
-  bcrypt = 'bcrypt.dll';
+var
+  BCryptFunctionsInitialized: BOOL;
 
-function BCryptCloseAlgorithmProvider(hAlgorithm: BCRYPT_ALG_HANDLE;
-  dwFlags: ULONG): NTSTATUS;
-  stdcall; external bcrypt;
+  BCryptCloseAlgorithmProvider: function(hAlgorithm: BCRYPT_ALG_HANDLE;
+    dwFlags: ULONG): NTSTATUS;
+    stdcall;
 
-function BCryptDestroyKey(hKey: BCRYPT_KEY_HANDLE): NTSTATUS;
-  stdcall; external bcrypt;
+  BCryptDestroyKey: function(hKey: BCRYPT_KEY_HANDLE): NTSTATUS;
+    stdcall;
 
-function BCryptExportKey(hKey: BCRYPT_KEY_HANDLE; hExportKey: BCRYPT_KEY_HANDLE;
-  pszBlobType: LPCWSTR; var pbOutput; cbOutput: ULONG; out pcbResult: ULONG;
-  dwFlags: ULONG): NTSTATUS;
-  stdcall; external bcrypt;
+  BCryptExportKey: function(hKey: BCRYPT_KEY_HANDLE; hExportKey: BCRYPT_KEY_HANDLE;
+    pszBlobType: LPCWSTR; var pbOutput; cbOutput: ULONG; out pcbResult: ULONG;
+    dwFlags: ULONG): NTSTATUS;
+    stdcall;
 
-function BCryptFinalizeKeyPair(hKey: BCRYPT_KEY_HANDLE; dwFlags: ULONG): NTSTATUS;
-  stdcall; external bcrypt;
+  BCryptFinalizeKeyPair: function(hKey: BCRYPT_KEY_HANDLE; dwFlags: ULONG): NTSTATUS;
+    stdcall;
 
-function BCryptGenerateKeyPair(hAlgorithm: BCRYPT_ALG_HANDLE;
-  out phKey: BCRYPT_KEY_HANDLE; dwLength: ULONG; dwFlags: ULONG): NTSTATUS;
-  stdcall; external bcrypt;
+  BCryptGenerateKeyPair: function(hAlgorithm: BCRYPT_ALG_HANDLE;
+    out phKey: BCRYPT_KEY_HANDLE; dwLength: ULONG; dwFlags: ULONG): NTSTATUS;
+    stdcall;
 
-function BCryptImportKeyPair(hAlgorithm: BCRYPT_ALG_HANDLE;
-  hImportKey: BCRYPT_KEY_HANDLE; pszBlobType: LPCWSTR;
-  out phKey: BCRYPT_KEY_HANDLE; const pbInput; cbInput: ULONG;
-  dwFlags: ULONG): NTSTATUS;
-  stdcall; external bcrypt;
+  BCryptImportKeyPair: function(hAlgorithm: BCRYPT_ALG_HANDLE;
+    hImportKey: BCRYPT_KEY_HANDLE; pszBlobType: LPCWSTR;
+    out phKey: BCRYPT_KEY_HANDLE; const pbInput; cbInput: ULONG;
+    dwFlags: ULONG): NTSTATUS;
+    stdcall;
 
-function BCryptOpenAlgorithmProvider(out phAlgorithm: BCRYPT_ALG_HANDLE;
-  pszAlgId: LPCWSTR; pszImplementation: LPCWSTR; dwFlags: ULONG): NTSTATUS;
-  stdcall; external bcrypt;
+  BCryptOpenAlgorithmProvider: function(out phAlgorithm: BCRYPT_ALG_HANDLE;
+    pszAlgId: LPCWSTR; pszImplementation: LPCWSTR; dwFlags: ULONG): NTSTATUS;
+    stdcall;
 
-function BCryptSignHash(hKey: BCRYPT_KEY_HANDLE; pPaddingInfo: Pointer;
-  const pbInput; cbInput: ULONG; var pbOutput; cbOutput: ULONG;
-  out pcbResult: ULONG; dwFlags: ULONG): NTSTATUS;
-  stdcall; external bcrypt;
+  BCryptSignHash: function(hKey: BCRYPT_KEY_HANDLE; pPaddingInfo: Pointer;
+    const pbInput; cbInput: ULONG; var pbOutput; cbOutput: ULONG;
+    out pcbResult: ULONG; dwFlags: ULONG): NTSTATUS;
+    stdcall;
 
-function BCryptVerifySignature(hKey: BCRYPT_KEY_HANDLE; pPaddingInfo: Pointer;
-  const pbHash; cbHash: ULONG; const pbSignature; cbSignature: ULONG;
-  dwFlags: ULONG): NTSTATUS;
-  stdcall; external bcrypt;
+  BCryptVerifySignature: function(hKey: BCRYPT_KEY_HANDLE; pPaddingInfo: Pointer;
+    const pbHash; cbHash: ULONG; const pbSignature; cbSignature: ULONG;
+    dwFlags: ULONG): NTSTATUS;
+    stdcall;
 
 type
   { ECDSA-P256 key blob formats specific to BCrypt }
@@ -133,6 +134,45 @@ type
     procedure Clear;
   end;
 
+procedure InitBCryptFunctions;
+var
+  M: HMODULE;
+
+  procedure InitFunc(out AProc: Pointer; const AProcName: PAnsiChar);
+  begin
+    AProc := GetProcAddress(M, AProcName);
+    if not Assigned(AProc) then
+      raise EECDSAError.CreateFmt('Failed to get address of %s in bcrypt.dll',
+        [AProcName]);
+  end;
+
+var
+  SystemDir: array[0..MAX_PATH-1] of Char;
+begin
+  if BCryptFunctionsInitialized then begin
+    MemoryBarrier;
+    Exit;
+  end;
+
+  GetSystemDirectory(SystemDir, SizeOf(SystemDir) div SizeOf(SystemDir[0]));
+  M := LoadLibrary(PChar(SystemDir + '\bcrypt.dll'));
+  if M = 0 then
+    raise EECDSAError.Create('Failed to load bcrypt.dll');
+
+  InitFunc(@BCryptCloseAlgorithmProvider, 'BCryptCloseAlgorithmProvider');
+  InitFunc(@BCryptDestroyKey, 'BCryptDestroyKey');
+  InitFunc(@BCryptExportKey, 'BCryptExportKey');
+  InitFunc(@BCryptFinalizeKeyPair, 'BCryptFinalizeKeyPair');
+  InitFunc(@BCryptGenerateKeyPair, 'BCryptGenerateKeyPair');
+  InitFunc(@BCryptImportKeyPair, 'BCryptImportKeyPair');
+  InitFunc(@BCryptOpenAlgorithmProvider, 'BCryptOpenAlgorithmProvider');
+  InitFunc(@BCryptSignHash, 'BCryptSignHash');
+  InitFunc(@BCryptVerifySignature, 'BCryptVerifySignature');
+
+  MemoryBarrier;
+  BCryptFunctionsInitialized := True;
+end;
+
 { TBCryptPrivateKeyBlob }
 
 procedure TBCryptPrivateKeyBlob.Clear;
@@ -173,6 +213,7 @@ end;
 constructor TECDSAKey.Create;
 begin
   inherited;
+  InitBCryptFunctions;
   var LAlgorithmHandle: BCRYPT_ALG_HANDLE;
   CheckStatus('BCryptOpenAlgorithmProvider',
     BCryptOpenAlgorithmProvider(LAlgorithmHandle, BCRYPT_ECDSA_P256_ALGORITHM,