Commit 9c68bba1 authored by Maxence MOHR's avatar Maxence MOHR 😄
Browse files

Moved work to thread, added search for public keys and certificates in a RO session

parent 92358f2d
......@@ -9,7 +9,7 @@ namespace PKCS11Explorer
{
get
{
return "0.2";
return "0.3";
}
}
public override void Initialize()
......
......@@ -4,7 +4,7 @@
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
<Platforms>AnyCPU;x64</Platforms>
<ApplicationIcon>app_icon.ico</ApplicationIcon>
<Version>0.0.2</Version>
<Version>0.3</Version>
<Authors>Maxence MOHR</Authors>
<Product>PKCS11 Explorer</Product>
<Copyright>PKCS11 Explorer under Apache 2.0 Licensee</Copyright>
......@@ -22,6 +22,7 @@
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.8.2" />
<PackageReference Include="Avalonia.Desktop" Version="0.8.2" />
<PackageReference Include="BouncyCastle" Version="1.8.5" />
<PackageReference Include="Pkcs11Interop" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
......
......@@ -12,61 +12,166 @@ namespace PKCS11Explorer.Tools
{
static class PKCS11Lister
{
public async static Task<Node> ListForTreeview(string PKCS11LibraryFilePath)
public static event EventHandler<ListForTreeviewEventArgs> ListForTreeviewFinished;
public async static Task ListForTreeview(string PKCS11LibraryFilePath)
{
try
{
// Create factories used by Pkcs11Interop library
Pkcs11InteropFactories factories = new Pkcs11InteropFactories();
// Create factories used by Pkcs11Interop library
Pkcs11InteropFactories factories = new Pkcs11InteropFactories();
Node Tree = new Node();
Node Tree = new Node();
// Load unmanaged PKCS#11 library
using (IPkcs11Library pkcs11Library = factories.Pkcs11LibraryFactory.LoadPkcs11Library(factories, PKCS11LibraryFilePath, AppType.SingleThreaded))
{
// Show general information about loaded library
ILibraryInfo libraryInfo = pkcs11Library.GetInfo();
Node Library = new Node() { Header = "PKCS11 Library " + libraryInfo.LibraryDescription, IconURI = "resm:PKCS11Explorer.Assets.baseline_layers_black_18dp.png" };
Library.Children.Add(new Node() { Header = "Filepath: " + PKCS11LibraryFilePath, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Library.Children.Add(new Node() { Header = "Manufacturer: " + libraryInfo.ManufacturerId, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Library.Children.Add(new Node() { Header = "Description: " + libraryInfo.LibraryDescription, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Library.Children.Add(new Node() { Header = "Version: " + libraryInfo.LibraryVersion, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
Tree.Children.Add(Library);
// Get list of all available slots
foreach (ISlot slot in pkcs11Library.GetSlotList(SlotsType.WithOrWithoutTokenPresent))
// Load unmanaged PKCS#11 library
using (IPkcs11Library pkcs11Library = factories.Pkcs11LibraryFactory.LoadPkcs11Library(factories, PKCS11LibraryFilePath, AppType.MultiThreaded))
{
// Show basic information about slot
ISlotInfo slotInfo = slot.GetSlotInfo();
Node Slot = new Node() { Header = "Slot " + slot.GetSlotInfo().SlotId, IconURI = "resm:PKCS11Explorer.Assets.baseline_scanner_black_18dp.png" };
Slot.Children.Add(new Node() { Header = "Manufacturer: " + slotInfo.ManufacturerId, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Slot.Children.Add(new Node() { Header = "Description: " + slotInfo.SlotDescription, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Slot.Children.Add(new Node() { Header = "Token present: " + slotInfo.SlotFlags.TokenPresent, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
if (slotInfo.SlotFlags.TokenPresent)
// Show general information about loaded library
ILibraryInfo libraryInfo = pkcs11Library.GetInfo();
Node Library = new Node() { Header = "PKCS11 Library " + libraryInfo.LibraryDescription, IconURI = "resm:PKCS11Explorer.Assets.baseline_layers_black_18dp.png" };
Library.Children.Add(new Node() { Header = "Filepath: " + PKCS11LibraryFilePath, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Library.Children.Add(new Node() { Header = "Manufacturer: " + libraryInfo.ManufacturerId, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Library.Children.Add(new Node() { Header = "Description: " + libraryInfo.LibraryDescription, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Library.Children.Add(new Node() { Header = "Version: " + libraryInfo.LibraryVersion, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
Tree.Children.Add(Library);
// Get list of all available slots
foreach (ISlot slot in pkcs11Library.GetSlotList(SlotsType.WithOrWithoutTokenPresent))
{
// Show basic information about token present in the slot
ITokenInfo tokenInfo = slot.GetTokenInfo();
// Show basic information about slot
ISlotInfo slotInfo = slot.GetSlotInfo();
Node Slot = new Node() { Header = "Slot " + slot.GetSlotInfo().SlotId, IconURI = "resm:PKCS11Explorer.Assets.baseline_scanner_black_18dp.png" };
Slot.Children.Add(new Node() { Header = "Manufacturer: " + slotInfo.ManufacturerId, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Slot.Children.Add(new Node() { Header = "Description: " + slotInfo.SlotDescription, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Slot.Children.Add(new Node() { Header = "Token present: " + slotInfo.SlotFlags.TokenPresent, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Node Token = new Node() { Header = "Token " + tokenInfo.SerialNumber, IconURI = "resm:PKCS11Explorer.Assets.baseline_sim_card_black_18dp.png" };
Token.Children.Add(new Node() { Header = "Manufacturer: " + tokenInfo.ManufacturerId, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Token.Children.Add(new Node() { Header = "Model: " + tokenInfo.Model, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Token.Children.Add(new Node() { Header = "Serial number: " + tokenInfo.SerialNumber, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Token.Children.Add(new Node() { Header = "Label: " + tokenInfo.Label, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Node SupportedMechanisms = new Node() { Header = "Supported mechanisms", IconURI = "resm:PKCS11Explorer.Assets.baseline_check_circle_black_18dp.png" };
// Show list of mechanisms (algorithms) supported by the token
foreach (CKM mechanism in slot.GetMechanismList())
if (slotInfo.SlotFlags.TokenPresent)
{
SupportedMechanisms.Children.Add(new Node() { Header = mechanism.ToString(), IconURI = "resm:PKCS11Explorer.Assets.baseline_check_circle_black_18dp.png" });
// Show basic information about token present in the slot
ITokenInfo tokenInfo = slot.GetTokenInfo();
Node Token = new Node() { Header = "Token " + tokenInfo.SerialNumber, IconURI = "resm:PKCS11Explorer.Assets.baseline_sim_card_black_18dp.png" };
Token.Children.Add(new Node() { Header = "Manufacturer: " + tokenInfo.ManufacturerId, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Token.Children.Add(new Node() { Header = "Model: " + tokenInfo.Model, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Token.Children.Add(new Node() { Header = "Serial number: " + tokenInfo.SerialNumber, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
Token.Children.Add(new Node() { Header = "Label: " + tokenInfo.Label, IconURI = "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png" });
if(tokenInfo.FreePublicMemory != uint.MaxValue)
Token.Children.Add(new Node() { Header = "Available public objects memory: " + tokenInfo.FreePublicMemory + " / " + tokenInfo.TotalPublicMemory, IconURI = "resm:PKCS11Explorer.Assets.baseline_memory_black_18dp.png" });
if (tokenInfo.TotalPrivateMemory != uint.MaxValue)
Token.Children.Add(new Node() { Header = "Available private objects memory: " + tokenInfo.FreePrivateMemory + " / " + tokenInfo.TotalPrivateMemory, IconURI = "resm:PKCS11Explorer.Assets.baseline_memory_black_18dp.png" });
// Show public keys name
Node pubkeyNode = new Node() { Header = "Public keys", IconURI = "resm:PKCS11Explorer.Assets.baseline_search_black_18dp.png" };
using (ISession session = slot.OpenSession(SessionType.ReadOnly))
{
// Do something interesting in RO session
var attrList = new List<IObjectAttribute>();
attrList.Add(factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
attrList.Add(factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
var objects = session.FindAllObjects(attrList);
foreach(var obj in objects)
{
if(obj.ObjectId != CK.CK_INVALID_HANDLE)
{
var objectHandle = factories.ObjectHandleFactory.Create(obj.ObjectId);
List<CKA> attributes = new List<CKA>();
attributes.Add(CKA.CKA_LABEL);
List<IObjectAttribute> objectAttributes = session.GetAttributeValue(objectHandle, attributes);
pubkeyNode.Children.Add(new Node() { Header = objectAttributes[0].GetValueAsString(), IconURI = "resm:PKCS11Explorer.Assets.baseline_vpn_key_black_18dp.png" });
Console.WriteLine("Found: " + objectAttributes[0].GetValueAsString());
}
}
session.CloseSession();
}
Token.Children.Add(pubkeyNode);
// Show private keys name
/*Node privkeyNode = new Node() { Header = "Private keys", IconURI = "resm:PKCS11Explorer.Assets.baseline_search_black_18dp.png" };
using (ISession session = slot.OpenSession(SessionType.ReadOnly))
{
session.Login(CKU.CKU_USER, "");
// Do something interesting in RO session
var attrList = new List<IObjectAttribute>();
attrList.Add(factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
attrList.Add(factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
var objects = session.FindAllObjects(attrList);
foreach (var obj in objects)
{
if (obj.ObjectId != CK.CK_INVALID_HANDLE)
{
var objectHandle = factories.ObjectHandleFactory.Create(obj.ObjectId);
List<CKA> attributes = new List<CKA>();
attributes.Add(CKA.CKA_LABEL);
List<IObjectAttribute> objectAttributes = session.GetAttributeValue(objectHandle, attributes);
privkeyNode.Children.Add(new Node() { Header = objectAttributes[0].GetValueAsString(), IconURI = "resm:PKCS11Explorer.Assets.baseline_vpn_key_black_18dp.png" });
Console.WriteLine("Found: " + objectAttributes[0].GetValueAsString());
}
}
session.Logout();
session.CloseSession();
}
Token.Children.Add(privkeyNode);
*/
// Show certs name
Node certsNode = new Node() { Header = "Certificates", IconURI = "resm:PKCS11Explorer.Assets.baseline_search_black_18dp.png" };
using (ISession session = slot.OpenSession(SessionType.ReadOnly))
{
// Do something interesting in RO session
var attrList = new List<IObjectAttribute>();
attrList.Add(factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_CERTIFICATE));
attrList.Add(factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
var objects = session.FindAllObjects(attrList);
foreach (var obj in objects)
{
if (obj.ObjectId != CK.CK_INVALID_HANDLE)
{
var objectHandle = factories.ObjectHandleFactory.Create(obj.ObjectId);
List<CKA> attributes = new List<CKA>();
attributes.Add(CKA.CKA_LABEL);
List<IObjectAttribute> objectAttributes = session.GetAttributeValue(objectHandle, attributes);
certsNode.Children.Add(new Node() { Header = objectAttributes[0].GetValueAsString(), IconURI = "resm:PKCS11Explorer.Assets.baseline_list_alt_black_18dp.png" });
Console.WriteLine("Found: " + objectAttributes[0].GetValueAsString());
}
}
session.CloseSession();
}
Token.Children.Add(certsNode);
// Show list of mechanisms (algorithms) supported by the token
Node SupportedMechanisms = new Node() { Header = "Supported mechanisms", IconURI = "resm:PKCS11Explorer.Assets.baseline_check_circle_black_18dp.png" };
foreach (CKM mechanism in slot.GetMechanismList())
{
SupportedMechanisms.Children.Add(new Node() { Header = mechanism.ToString(), IconURI = "resm:PKCS11Explorer.Assets.baseline_check_circle_black_18dp.png" });
}
Token.Children.Add(SupportedMechanisms);
Slot.Children.Add(Token);
}
Token.Children.Add(SupportedMechanisms);
Slot.Children.Add(Token);
}
Tree.Children.Add(Slot);
Tree.Children.Add(Slot);
}
}
ListForTreeviewFinished?.Invoke(Tree, new ListForTreeviewEventArgs() { MainNode = Tree, Success=true });
}
catch (Net.Pkcs11Interop.Common.UnmanagedException exception)
{
ListForTreeviewFinished?.Invoke(exception, new ListForTreeviewEventArgs() { UnmanagedException = exception, Success=false });
}
return Tree;
catch (Net.Pkcs11Interop.Common.Pkcs11Exception exception)
{
ListForTreeviewFinished?.Invoke(exception, new ListForTreeviewEventArgs() { Pkcs11Exception = exception, Success = false });
}
return;
}
}
public class ListForTreeviewEventArgs : EventArgs
{
public bool Success { get; set; }
public Node MainNode { get; set; }
public Net.Pkcs11Interop.Common.UnmanagedException UnmanagedException { get; set; }
public Net.Pkcs11Interop.Common.Pkcs11Exception Pkcs11Exception { get; set; }
}
}
......@@ -15,6 +15,7 @@ using Avalonia.Media.Imaging;
using System.Reflection;
using PKCS11Explorer.Tools;
using PKCS11Explorer.Views;
using Avalonia.Threading;
namespace PKCS11Explorer.Views
{
......@@ -54,7 +55,7 @@ namespace PKCS11Explorer.Views
MyTreeView.Width = Double.NaN;
MyTreeView.Height = Double.NaN;
MyTreeView.IsVisible = false;
LoadingBox = new LoadingBox("Please wait", "Loading PKCS11 middleware and looking for devices...", "resm:PKCS11Explorer.Assets.baseline_hourglass_empty_black_18dp.png");
PKCS11Lister.ListForTreeviewFinished += OnListForTreeviewFinished;
}
private async void ButtonHandler_LoadFile(object sender, RoutedEventArgs e)
......@@ -80,37 +81,58 @@ namespace PKCS11Explorer.Views
Console.WriteLine("Canceled file selection");
else
{
LoadingBox = new LoadingBox("Please wait", "Loading PKCS11 middleware and looking for devices...", "resm:PKCS11Explorer.Assets.baseline_hourglass_empty_black_18dp.png");
LoadingBox.ShowDialog(this);
Console.WriteLine("Selected file: " + fileSelected[0]);
Console.WriteLine("Loading informations, please wait.");
try
Task.Run(async () => { await PKCS11Lister.ListForTreeview(fileSelected[0]); });
}
}
private void OnListForTreeviewFinished(object sender, ListForTreeviewEventArgs eventArgs)
{
Dispatcher.UIThread.InvokeAsync(() =>
{
LoadingBox.Close();
if(eventArgs.Success)
{
Tree = await PKCS11Lister.ListForTreeview(fileSelected[0]);
Console.WriteLine("Loading done. refreshing UI.");
Tree = eventArgs.MainNode;
DataContext = Tree.Children;
MyTreeView.IsVisible = true;
}
catch (Net.Pkcs11Interop.Common.UnmanagedException exception)
else
{
if (exception.Message.Contains("Unable to get pointer for C_GetFunctionList function. Error code: 0x0000007F."))
if (eventArgs.UnmanagedException != null && eventArgs.UnmanagedException.Message.Contains("Unable to get pointer for C_GetFunctionList function. Error code: 0x0000007F."))
{
Console.WriteLine("Not a PKCS11 middleware, aborting.");
var dialog = new DialogBox("Error", "The loaded library is not a valid PKCS11 middleware.", "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png", "Ok");
await dialog.ShowDialog(this);
dialog.ShowDialog(this);
}
else if (eventArgs.UnmanagedException != null)
{
Console.WriteLine("Problem with provided middleware: " + eventArgs.UnmanagedException.Message);
var dialog = new DialogBox("Error", eventArgs.UnmanagedException.Message, "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png", "Ok");
dialog.ShowDialog(this);
}
else if (eventArgs.Pkcs11Exception != null)
{
Console.WriteLine("Problem with PKCS11: " + eventArgs.Pkcs11Exception.Message);
var dialog = new DialogBox("Error", eventArgs.Pkcs11Exception.Message, "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png", "Ok");
dialog.ShowDialog(this);
}
else
{
Console.WriteLine("Problem with provided middleware: " + exception.Message);
Console.WriteLine("Unmanaged exception");
var dialog = new DialogBox("Error", "Unmanaged exception", "resm:PKCS11Explorer.Assets.baseline_info_black_18dp.png", "Ok");
dialog.ShowDialog(this);
}
}
catch (Net.Pkcs11Interop.Common.Pkcs11Exception exception)
{
Console.WriteLine("Not a PKCS11 middleware: " + exception.Message);
}
LoadingBox.Close();
}
});
}
public class Node
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment