120 lines
3.9 KiB
C#
120 lines
3.9 KiB
C#
using EnvelopeGenerator.Application.Common.Configurations;
|
|
|
|
namespace EnvelopeGenerator.Infrastructure.Crypt.Services;
|
|
|
|
internal static class Pkcs11InteropBootstrap
|
|
{
|
|
private static readonly object Sync = new();
|
|
private static bool Initialized;
|
|
private const string ProxyRelativePath = "pkcs11\\windows\\proxy\\libpkcs11-proxy.dll";
|
|
private const string ToolRelativePath = "pkcs11\\windows\\opensc\\tools\\pkcs11-tool.exe";
|
|
|
|
public static void EnsureLoaded(Pkcs11Options options)
|
|
{
|
|
if (Initialized)
|
|
return;
|
|
|
|
lock (Sync)
|
|
{
|
|
if (Initialized)
|
|
return;
|
|
|
|
var libraryPath = ResolveLibraryPath(options);
|
|
var toolPath = ResolveToolPath(options);
|
|
options.SetResolvedPaths(libraryPath, toolPath);
|
|
|
|
EnsureNativeDependencySearchPath(options.ResolvedLibraryPath);
|
|
|
|
if (!string.IsNullOrWhiteSpace(options.ProxySocket))
|
|
{
|
|
Environment.SetEnvironmentVariable("PKCS11_PROXY_SOCKET", options.ProxySocket);
|
|
Environment.SetEnvironmentVariable("PKCS11_DAEMON_SOCKET", options.ProxySocket);
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(options.ResolvedToolPath))
|
|
{
|
|
var toolDir = Path.GetDirectoryName(options.ResolvedToolPath);
|
|
if (!string.IsNullOrWhiteSpace(toolDir))
|
|
EnsurePathContains(toolDir);
|
|
}
|
|
|
|
WarmupWithPkcs11Tool(options);
|
|
Initialized = true;
|
|
}
|
|
}
|
|
|
|
private static string ResolveLibraryPath(Pkcs11Options options)
|
|
{
|
|
var assetsRoot = string.IsNullOrWhiteSpace(options.AssetsRootPath)
|
|
? AppContext.BaseDirectory
|
|
: options.AssetsRootPath;
|
|
|
|
var resolved = Path.Combine(assetsRoot, ProxyRelativePath);
|
|
if (File.Exists(resolved))
|
|
return resolved;
|
|
|
|
throw new FileNotFoundException($"PKCS#11 proxy module not found. Checked path: {resolved}", resolved);
|
|
}
|
|
|
|
private static string? ResolveToolPath(Pkcs11Options options)
|
|
{
|
|
var assetsRoot = string.IsNullOrWhiteSpace(options.AssetsRootPath)
|
|
? AppContext.BaseDirectory
|
|
: options.AssetsRootPath;
|
|
|
|
var resolved = Path.Combine(assetsRoot, ToolRelativePath);
|
|
if (File.Exists(resolved))
|
|
return resolved;
|
|
|
|
return null;
|
|
}
|
|
|
|
private static void WarmupWithPkcs11Tool(Pkcs11Options options)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(options.ResolvedToolPath))
|
|
return;
|
|
|
|
if (!File.Exists(options.ResolvedToolPath))
|
|
return;
|
|
|
|
var process = new System.Diagnostics.Process
|
|
{
|
|
StartInfo = new System.Diagnostics.ProcessStartInfo
|
|
{
|
|
FileName = options.ResolvedToolPath,
|
|
Arguments = $"--module \"{options.ResolvedLibraryPath}\" -L",
|
|
UseShellExecute = false,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
CreateNoWindow = true
|
|
}
|
|
};
|
|
|
|
process.Start();
|
|
process.WaitForExit(15000);
|
|
}
|
|
|
|
private static void EnsureNativeDependencySearchPath(string libraryPath)
|
|
{
|
|
var directory = Path.GetDirectoryName(libraryPath);
|
|
if (string.IsNullOrWhiteSpace(directory))
|
|
return;
|
|
|
|
EnsurePathContains(directory);
|
|
}
|
|
|
|
private static void EnsurePathContains(string directory)
|
|
{
|
|
var currentPath = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
|
|
var entries = currentPath.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
|
if (entries.Any(p => string.Equals(p, directory, StringComparison.OrdinalIgnoreCase)))
|
|
return;
|
|
|
|
var updatedPath = string.IsNullOrWhiteSpace(currentPath)
|
|
? directory
|
|
: directory + ";" + currentPath;
|
|
|
|
Environment.SetEnvironmentVariable("PATH", updatedPath);
|
|
}
|
|
}
|